[英]Splitting dataframe into multiple dataframes
我有一個非常大的數據框(大約 100 萬行),其中包含來自實驗的數據(60 名受訪者)。
我想將數據框分成 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
我沒有收到錯誤消息,腳本似乎永遠運行!
有聰明的方法嗎?
我可以問為什么不通過切片數據框來做到這一點。 就像是
#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']
希望有幫助
首先,您的方法效率低下,因為逐行附加到列表會很慢,因為當新條目的空間不足時,它必須定期增加列表,列表理解在這方面更好,因為大小已確定前面並分配一次。
但是,我認為從根本上講,您的方法有點浪費,因為您已經有了一個數據框,那么為什么要為這些用戶中的每一個都創建一個新的呢?
我會按列'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'
您可以將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
簡單:
[v for k, v in df.groupby('name')]
Groupby 可以幫助您:
grouped = data.groupby(['name'])
然后,您可以像處理每個參與者的數據框一樣處理每個組。 而DataFrameGroupBy對象的方法如(apply、transform、aggregate、head、first、last)返回一個DataFrame對象。
或者您可以從grouped
創建列表grouped
索引獲取所有數據幀:
l_grouped = list(grouped)
l_grouped[0][1]
- 具有名字的第一個組的數據幀。
除了 Gusev Slava 的回答之外,您可能還想使用 groupby 的組:
{key: df.loc[value] for key, value in df.groupby("name").groups.items()}
這將生成一個字典,其中包含您分組的鍵,指向相應的分區。 優點是鍵被維護並且不會在列表索引中消失。
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)
Sum 被 cythonized 這就是為什么它如此之快
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
基於列表理解和groupby
- 將所有拆分數據幀存儲在列表變量中,並且可以使用索引進行訪問。
例子
ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)]
ans[0]
ans[0].column_name
'method'
列上使用.groupby
,並使用dict
DataFrames
以唯一的'method'
值作為鍵創建DataFrames
的dict-comprehension
。
.groupby
返回一個groupby
對象,其中包含有關組的信息,其中g
是每個組的'method'
的唯一值, d
是該組的DataFrame
。df_dict
中每個key
的value
將是一個DataFrame
,可以以標准方式訪問, df_dict['key']
。DataFrames
list
,這可以通過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)
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
創建單獨DataFrames
的手動方法:布爾索引.loc
。DataFrames
的可接受方法。dict
、 list
、 generator
等),如上所示。df1 = df[df.method == 'Astrometry']
df2 = df[df.method == 'Eclipse Timing Variations']
如果您的數據已有一些標簽,則可以使用 groupby 命令。
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
跑
out_list = [group[1] for group in in_series.groupby(label_series.values)]
它返回out_list
兩個pd.Series
的list
:
[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
這是一個可能對某些人有所幫助的小函數(效率可能並不完美,但緊湊 + 或多或少易於理解):
def get_splited_df_dict(df: 'pd.DataFrame', split_column: 'str'):
"""
splits a pandas.DataFrame on split_column and returns it as a dict
"""
df_dict = {value: df[df[split_column] == value].drop(split_column, axis=1) for value in df[split_column].unique()}
return df_dict
它通過選擇給定列中的每個唯一值並將所有這些條目放入單獨的 DataFrame 中,將一個 DataFrame 轉換為多個 DataFrame。 .drop(split_column, axis=1)
僅用於刪除用於拆分 DataFrame 的列。 刪除不是必需的,但可以幫助減少操作后的內存使用量。
get_splited_df_dict
的結果是一個dict
,這意味着可以像這樣訪問每個 DataFrame:
splitted = get_splited_df_dict(some_df, some_column)
# accessing the DataFrame with 'some_column_value'
splitted[some_column_value]
現有的答案涵蓋了所有好的案例,並且很好地解釋了groupby
對象如何像一個可以通過.groups
訪問的鍵和值的字典。 還有更多方法可以完成與現有答案相同的工作:
dict([*df.groupby('Name')]) # same as dict(list(df.groupby('Name')))
dict((*df.groupby('Name'),))
[*dict([*df.groupby('Name')]).values()]
我有類似的問題。 我有 10 家不同商店和 50 種不同商品的每日銷售額的時間序列。 我需要將原始數據幀拆分為 500 個數據幀(10 個商店 * 50 個商店)以將機器學習模型應用於每個數據幀,而我無法手動完成。
這是數據幀的頭部:
我創建了兩個列表; 一個用於數據幀的名稱,另一個用於數組 [item_number, store_number]。
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 個數據幀。
希望這會有所幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.