डेटाफ़्रेम को कई डेटाफ़्रेम में विभाजित करना


92

मेरे पास एक प्रयोग (60 उत्तरदाताओं) के डेटा के साथ एक बहुत बड़ी डेटाफ़्रेम (लगभग 1 मिलियन पंक्तियाँ) हैं।

मैं डेटाफ़्रेम को 60 डेटाफ़्रेम (प्रत्येक प्रतिभागी के लिए एक डेटाफ़्रेम) में विभाजित करना चाहूंगा।

डेटाफ्रेम में, dataएक चर कहा जाता है 'name', जो प्रत्येक प्रतिभागी के लिए अद्वितीय कोड है।

मैंने निम्नलिखित कोशिश की है, लेकिन कुछ भी नहीं होता है (या निष्पादन एक घंटे के भीतर बंद नहीं होता है)। मैं जो करने का इरादा रखता हूं, dataउसे छोटे डेटाफ़्रेम में विभाजित करना है , और इन्हें एक सूची में जोड़ना है ( datalist):

import pandas as pd

def splitframe(data, name='name'):
    
    n = data[name][0]

    df = pd.DataFrame(columns=data.columns)

    datalist = []

    for i in range(len(data)):
        if data[name][i] == n:
            df = df.append(data.iloc[i])
        else:
            datalist.append(df)
            df = pd.DataFrame(columns=data.columns)
            n = data[name][i]
            df = df.append(data.iloc[i])
        
    return datalist

मुझे एक त्रुटि संदेश नहीं मिलता है, स्क्रिप्ट बस हमेशा के लिए चलने लगती है!

क्या इसे करने का कोई स्मार्ट तरीका है?

जवाबों:


53

सबसे पहले आपका दृष्टिकोण अक्षम है क्योंकि किसी पंक्ति के आधार पर सूची में जोड़ना धीमा हो जाएगा क्योंकि यह समय-समय पर सूची में वृद्धि करता है जब नई प्रविष्टि के लिए अपर्याप्त स्थान होता है, इस संदर्भ में सूची समझ बेहतर होती है क्योंकि आकार निर्धारित किया जाता है। एक बार सामने और आवंटित किया गया।

हालाँकि, मुझे लगता है कि मौलिक रूप से आपका दृष्टिकोण थोड़ा बेकार है क्योंकि आपके पास पहले से ही एक डेटाफ्रेम है इसलिए इनमें से प्रत्येक उपयोगकर्ता के लिए एक नया क्यों बनाएं?

मैं कॉलम द्वारा डेटाफ्रेम सॉर्ट करूंगा 'name', इंडेक्स को यह होना चाहिए और यदि आवश्यक नहीं है तो कॉलम को छोड़ दें।

फिर सभी अद्वितीय प्रविष्टियों की एक सूची तैयार करें और फिर आप इन प्रविष्टियों का उपयोग करके एक लुकअप प्रदर्शन कर सकते हैं और यदि आप डेटा को केवल क्वेरी कर रहे हैं, तो डेटाफ़्रेम पर एक महंगा डेटा कॉपी बिना किसी दृश्य को वापस करने के लिए चयन मानदंड का उपयोग करें।

उपयोग pandas.DataFrame.sort_valuesऔर pandas.DataFrame.set_index:

# sort the dataframe
df.sort_values(by='name', axis=1, inplace=True)

# set the index to be this and don't drop
df.set_index(keys=['name'], drop=False,inplace=True)

# get a list of names
names=df['name'].unique().tolist()

# now we can perform a lookup on a 'view' of the dataframe
joe = df.loc[df.name=='joe']

# now you can query all 'joes'

74

क्या मैं पूछ सकता हूं कि सिर्फ डेटा फ्रेम को कटाकर ही ऐसा क्यों न किया जाए। कुछ इस तरह

#create some data with Names column
data = pd.DataFrame({'Names': ['Joe', 'John', 'Jasper', 'Jez'] *4, 'Ob1' : np.random.rand(16), 'Ob2' : np.random.rand(16)})

#create unique list of names
UniqueNames = data.Names.unique()

#create a data frame dictionary to store your data frames
DataFrameDict = {elem : pd.DataFrame for elem in UniqueNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names == key]

अरे प्रेस्टो आपके पास डेटा फ्रेम का एक शब्दकोश है जैसा कि (मुझे लगता है) आप उन्हें चाहते हैं। एक का उपयोग करने की आवश्यकता है? बस दर्ज करें

DataFrameDict['Joe']

उम्मीद है की वो मदद करदे


38

आप groupbyऑब्जेक्ट को tuplesतब और उसके बाद में बदल सकते हैं dict:

df = pd.DataFrame({'Name':list('aabbef'),
                   'A':[4,5,4,5,5,4],
                   'B':[7,8,9,4,2,3],
                   'C':[1,3,5,7,1,0]}, columns = ['Name','A','B','C'])

print (df)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3
2    b  4  9  5
3    b  5  4  7
4    e  5  2  1
5    f  4  3  0

d = dict(tuple(df.groupby('Name')))
print (d)
{'b':   Name  A  B  C
2    b  4  9  5
3    b  5  4  7, 'e':   Name  A  B  C
4    e  5  2  1, 'a':   Name  A  B  C
0    a  4  7  1
1    a  5  8  3, 'f':   Name  A  B  C
5    f  4  3  0}

print (d['a'])
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3

यह अनुशंसित नहीं है , लेकिन समूहों द्वारा डेटाफ्रैम बनाना संभव है:

for i, g in df.groupby('Name'):
    globals()['df_' + str(i)] =  g

print (df_a)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3


16

ग्रुपबी आपकी मदद कर सकता है:

grouped = data.groupby(['name'])

फिर आप प्रत्येक भागीदार के लिए डेटाफ़्रेम के साथ प्रत्येक समूह के साथ काम कर सकते हैं। और DataFrameGroupBy ऑब्जेक्ट तरीके जैसे (लागू करें, रूपांतरित करें, एकत्रित करें, सिर, पहले, आखिरी) एक DataFrame ऑब्जेक्ट वापस करें।

या आप groupedसभी डेटाफ़्रेम को इंडेक्स द्वारा सूची बना सकते हैं और प्राप्त कर सकते हैं :

l_grouped = list(grouped)

l_grouped[0][1] - पहले नाम के साथ पहले समूह के लिए डेटाफ्रेम।


7

गुसेव स्लावा के उत्तर के अलावा, आप समूह के समूहों का उपयोग करना चाह सकते हैं:

{key: df.loc[value] for key, value in df.groupby("name").groups.items()}

इससे संबंधित विभाजनों की ओर इशारा करते हुए, आपके द्वारा समूहीकृत की गई कुंजी के साथ एक शब्दकोश मिलेगा। लाभ यह है कि चाबियाँ बनाए रखी जाती हैं और सूची सूचकांक में गायब नहीं होती हैं।


3
In [28]: df = DataFrame(np.random.randn(1000000,10))

In [29]: df
Out[29]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [30]: frames = [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]

In [31]: %timeit [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]
1 loops, best of 3: 849 ms per loop

In [32]: len(frames)
Out[32]: 16667

यहां एक समूह तरीका है (और आप राशि के बजाय एक मनमाना आवेदन कर सकते हैं)

In [9]: g = df.groupby(lambda x: x/60)

In [8]: g.sum()    

Out[8]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 16667 entries, 0 to 16666
Data columns (total 10 columns):
0    16667  non-null values
1    16667  non-null values
2    16667  non-null values
3    16667  non-null values
4    16667  non-null values
5    16667  non-null values
6    16667  non-null values
7    16667  non-null values
8    16667  non-null values
9    16667  non-null values
dtypes: float64(10)

सम को साइंटिफ़ाइंड किया जाता है यही कारण है कि यह इतना तेज़ है

In [10]: %timeit g.sum()
10 loops, best of 3: 27.5 ms per loop

In [11]: %timeit df.groupby(lambda x: x/60)
1 loops, best of 3: 231 ms per loop

1

सूची समझ पर आधारित विधि और groupby- जो सूची चर में सभी विभाजन डेटाफ्रेम को संग्रहीत करती है और सूचकांक का उपयोग करके पहुँचा जा सकता है।

उदाहरण

ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)]

ans[0]
ans[0].column_name

1
  • सबसे पहले, ओपी में विधि काम करती है, लेकिन कुशल नहीं है। यह हमेशा के लिए चलाने के लिए लग रहा था, क्योंकि डेटासेट लंबा था।
  • स्तंभ .groupbyपर उपयोग करें 'method', और कुंजियों के रूप में अद्वितीय मानों dictके DataFramesसाथ बनाएँ, एक के साथ । 'method'dict-comprehension
    • .groupbyएक groupbyवस्तु लौटाता है , जिसमें समूहों के बारे में जानकारी होती है, जहां प्रत्येक समूह के लिए gअद्वितीय मूल्य है 'method', और उस समूह dके DataFrameलिए है।
  • valueप्रत्येक के keyमें df_dict, एक हो जाएगा DataFrameजो मानक तरीके से पहुँचा जा सकता है,, df_dict['key']
  • मूल प्रश्न चाहता था एक listकी DataFramesहै जो एक साथ किया जा सकता,list-comprehension
    • df_list = [d for _, d in df.groupby('method')]
import pandas as pd
import seaborn as sns  # for test dataset

# load data for example
df = sns.load_dataset('planets')

# display(df.head())
            method  number  orbital_period   mass  distance  year
0  Radial Velocity       1         269.300   7.10     77.40  2006
1  Radial Velocity       1         874.774   2.21     56.95  2008
2  Radial Velocity       1         763.000   2.60     19.84  2011
3  Radial Velocity       1         326.030  19.40    110.62  2007
4  Radial Velocity       1         516.220  10.50    119.47  2009


# Using a dict-comprehension, the unique 'method' value will be the key
df_dict = {g: d for g, d in df.groupby('method')}

print(df_dict.keys())
[out]:
dict_keys(['Astrometry', 'Eclipse Timing Variations', 'Imaging', 'Microlensing', 'Orbital Brightness Modulation', 'Pulsar Timing', 'Pulsation Timing Variations', 'Radial Velocity', 'Transit', 'Transit Timing Variations'])

# or a specific name for the key, using enumerate (e.g. df1, df2, etc.)
df_dict = {f'df{i}': d for i, (g, d) in enumerate(df.groupby('method'))}

print(df_dict.keys())
[out]:
dict_keys(['df0', 'df1', 'df2', 'df3', 'df4', 'df5', 'df6', 'df7', 'df8', 'df9'])
  • df_dict['df1].head(3) या df_dict['Astrometry'].head(3)
  • इस समूह में केवल 2 हैं
         method  number  orbital_period  mass  distance  year
113  Astrometry       1          246.36   NaN     20.77  2013
537  Astrometry       1         1016.00   NaN     14.98  2010
  • df_dict['df2].head(3) या df_dict['Eclipse Timing Variations'].head(3)
                       method  number  orbital_period  mass  distance  year
32  Eclipse Timing Variations       1         10220.0  6.05       NaN  2009
37  Eclipse Timing Variations       2          5767.0   NaN    130.72  2008
38  Eclipse Timing Variations       2          3321.0   NaN    130.72  2008
  • df_dict['df3].head(3) या df_dict['Imaging'].head(3)
     method  number  orbital_period  mass  distance  year
29  Imaging       1             NaN   NaN     45.52  2005
30  Imaging       1             NaN   NaN    165.00  2007
31  Imaging       1             NaN   NaN    140.00  2004

वैकल्पिक रूप से

  • पंडोंDataFrames का उपयोग करके अलग बनाने के लिए यह एक मैनुअल विधि है : बूलियन इंडेक्सिंग
  • यह स्वीकृत उत्तर के समान है , लेकिन .locइसकी आवश्यकता नहीं है।
  • यह एक जोड़े को अतिरिक्त बनाने के लिए एक स्वीकार्य तरीका है DataFrames
  • Pythonic तरीका से अधिक ऑब्जेक्ट बनाने के लिए, (उदाहरण के लिए एक कंटेनर में उन्हें रखने के द्वारा होता है dict, list, generatorजैसा कि ऊपर दिखाया,, आदि)।
df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']

0

यदि आप पहले से ही अपने डेटा के लिए कुछ लेबल रखते हैं, तो आप ग्रुपबी कमांड का उपयोग कर सकते हैं।

 out_list = [group[1] for group in in_series.groupby(label_series.values)]

यहाँ एक विस्तृत उदाहरण दिया गया है:

मान लें कि हम कुछ लेबलों का उपयोग करके एक pd श्रृंखला को विभाजन की सूची में बाँटना चाहते हैं उदाहरण के लिए, in_seriesहै:

2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00    1.16
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 5, dtype: float64

और इसके अनुरूप label_seriesहै:

2019-07-01 08:00:00   1
2019-07-01 08:02:00   1
2019-07-01 08:04:00   2
2019-07-01 08:06:00   2
2019-07-01 08:08:00   2
Length: 5, dtype: float64

Daud

out_list = [group[1] for group in in_series.groupby(label_series.values)]

जो दो में से out_listएक लौटाता है :listpd.Series

[2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00   1.16
Length: 2, dtype: float64,
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 3, dtype: float64]

ध्यान दें कि आप in_seriesश्रृंखला के समूह के लिए स्वयं से कुछ मापदंडों का उपयोग कर सकते हैं , उदाहरण के लिए,in_series.index.day


-1

मुझे भी ऐसी ही समस्या थी। मेरे पास 10 अलग-अलग दुकानों और 50 अलग-अलग वस्तुओं के लिए दैनिक बिक्री की एक समय श्रृंखला थी। मुझे उनमें से प्रत्येक को मशीन लर्निंग मॉडल लागू करने के लिए 500 डेटाफ्रेम (10 करोड़ * 50 करोड़) में मूल डेटाफ्रेम को विभाजित करने की आवश्यकता थी और मैं इसे मैन्युअल रूप से नहीं कर सका।

यह डेटाफ्रेम का प्रमुख है:

डेटाफ्रेम का प्रमुख: df

मैंने दो सूचियाँ बनाई हैं; डेटाफ्रेम के नाम के लिए एक और सरणी के दो के लिए एक [मद_नंबर, स्टोर_नंबर]।

    list=[]
    for i in range(1,len(items)*len(stores)+1):
    global list
    list.append('df'+str(i))

    list_couple_s_i =[]
    for item in items:
          for store in stores:
                  global list_couple_s_i
                  list_couple_s_i.append([item,store])

और एक बार दो सूचियां तैयार हो जाने के बाद आप उन वांछित डेटाफ्रेम को बनाने के लिए उन पर लूप कर सकते हैं:

         for name, it_st in zip(list,list_couple_s_i):
                   globals()[name] = df.where((df['item']==it_st[0]) & 
                                                (df['store']==(it_st[1])))
                   globals()[name].dropna(inplace=True)

इस तरह मैंने 500 डेटाफ्रेम बनाए हैं।

आशा है कि यह मददगार होगा!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.