目錄
一、分組
1.Groupby分組
當源數據是DataFrame類型時,groupby()方法返回一個DataFrameGroupBy對象。
若源數據是Series類型,則返回SeriesGroupBy對象。
import numpy as np
from pandas import DataFrame,Series
#(1)運行numpy的groupby方法分組
df=DataFrame({'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
print (df)
此時的df是dataframe對象
grouped是一個GroupBy對象,它實際上還沒有進行任何計算,只是含有一些有關分組鍵df['key1']的中間數據而己。
換句話說,該對象已經有了接下來對各分組執行運算所需的一切信息。
我們可以調用GroupBy的mean方法來計算分組平均值,也可以調用其他方法。
grouped=df['data1'].groupby(df['key1']) #data1數據按key1進行分組
print(grouped)
grouped0=df['data1'].groupby(df['key1']).mean()
print(grouped0)
groupedall=df.groupby(df['key1']).mean()#data1數據進行分組
print(groupedall)
grouped1=df['data1'].groupby([df['key1'],df['key2']]).mean()
print(grouped1)
df.groupby(['key1','key2'])[['data1']].mean()
#grouped1=df['data1'].groupby([df['key1'],df['key2']]).mean()效果一樣
2.對分組進行迭代
for name,group in df.groupby('key1'):
print (name)#就是a,b
print (group)#df的一部分
for k1,group in df.groupby(['key1','key2']):
print (k1)#('a', 'one')('a', 'two')('b', 'one')('b', 'two')
print(group)
當然,你可以對這些數據片段做任何操作。有一個有用的運算:將這些數據片段做成一個字典:dict(list(df.groupby('')))
pieces=list(df.groupby('key1'))
pieces#是兩個元胞的列表,兩個元胞均有兩個元素,一個是字母,一個是dataframe對象
print(pieces)
dpieces=dict(list(df.groupby('key1')))#將列表pieces轉化爲字典 鍵:a,b 值:兩個表
print(dpieces)
groupby默認是在axis=0(行)上進行分組,通過設置也可以在其他任何軸上進行分組:axis=1(列)
print (df.dtypes)
grouped=df.groupby(df.dtypes,axis=1)#鍵:dtype('float64') dtype('O'),值:表的一部分
print (dict(list(grouped)))
3.通過字典或Series進行分組
import numpy as np
from pandas import DataFrame,Series
people=DataFrame([[1,0,1,2,1],
[0,2,3,1,0],
[1,2,3,0,1],
[-1,0,-1,2,0],
[2,3,1,-2,0]],
columns=['a','b','c','d','e'],
index=['Joe','Steve','Wes','Jim','Travis'])
people.ix[2:3,['b','c']]=np.nan #ix[2:3]行索引爲[2:3],索引切片不包括3,'b','c'列的值爲Nan
print(people)
#(1)假設己知列的分組關係,並希望根據分組計算列的總計:
mapping={'a':'red','b':'red','c':'blue',
'd':'blue','e':'red','f':'orange'}
#現在只需將這個字典傳給groupby即可:
by_column=people.groupby(mapping,axis=1)
print (by_column.sum())
#輸出結果如下:'c','d'相加存入blue中,其它的相加放入red中
#(2) Series也有同樣的功能,它可以被看做一個固定大小的映射。
#對於上面的那個例子,如果用Series作爲分組鍵,則pandas會檢查Series以確保其索引跟分組軸是對齊的:
map_series=Series(mapping)
print (map_series)
print (people.groupby(map_series,axis=1).count())
4.通過函數進行分組
print( people.groupby(len).sum())#3是Joe,wes,Jim 在a,b,c,d,e列相加
#5只有steve一個人,故steve的數據抄下來即可
key_list=['one','one','one','two','two']
#將函數跟數組、列表、字典、Series混合使用,因爲任何東西最終都會被轉換爲數組:
print(people.groupby([len,key_list]).min())
5.根據索引級別分組
層次化索引數據集就在於它能夠根據索引級別進行聚合。要實現該目的,通過Level關鍵字傳入級別編號或名稱即可:
import numpy as np
from pandas import DataFrame,Series
import pandas as pd
#構建多級索引列
columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],
[1,3,5,1,3]],names=['cty','tenor'])
hier_df=DataFrame(np.random.randn(4,5),columns=columns)
print (hier_df)
print (hier_df.groupby(level='cty',axis=1).count()) #axis=1列分組,count是取總計的個數
二、聚合
通過GroupBy對象提供的agg()、transform()、filter()以及apply()等方法可以實現各種分組運算。每個方法的第一個參數都是一個回調函數,該函數對每個分組的數據進行運算並返回結果。這些方法根據回調函數的返回結果生成最終的分組運算結果。
1.agg()聚合
agg()對每個分組中的數據進行聚合運算。其回調函數接收的數據是表示每個分組中每列數據的Series對象,若回調函數不能處理
Series對象,則agg()會接着嘗試將整個分組的數據作爲DataFrame對象傳遞給回調函數。下面的其他方法也是如此。
回調函數對其參數進行聚合運算,將Series對象轉換爲單個數值,或將DataFrame對象轉換爲Series對象。
agg()返回一個DataFrame對象,其行索引爲每個分組的鍵,而列索引爲源數據的列索引。
import numpy as np
from pandas import DataFrame,Series
import pandas as pd
df=DataFrame({'key1':['a','a','b','b','a'],
'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),
'data2':np.random.randn(5)})
grouped=df.groupby('key1')
#自定義函數
def peak_to_peak(arr):
return arr.max()-arr.min()
print (grouped.agg(peak_to_peak))
#匿名函數
#df.groupby('key1').agg(lambda df:df.max()-df.min())
df=pd.DataFrame([[1,2],[5,6],[9,4],[7,0],[3,8]],columns=['A','B'])
df['key']=['a','a','a','b','b']
print(df)
g=df.groupby('key')
"""
由
於np.max()能對Series對象進行運算,因此agg()將分組a和分組b中的每列數據分別傳遞給
np.max()以計算每列的最大值,並將所有最大值聚合成一個DataFrame對象。
"""
print(g.agg(np.max))
"""
由於在回調函數中訪問了屬性A和B,這兩個屬性在表示每列數據的Series對象中不存在,因此傳遞Series對象給回調函數的嘗試失敗。於是agg()接下來嘗試將表示整個分組數據的DataFrame對象傳遞給回調函數。該回調函數每次返回結果中的一行,例如圖中分組b對應的運算結果爲第b行。該回調函數返回每個分組中A+B最大的那一行。
"""
print(g.agg(lambda df:df.loc[(df.A+df.B).idxmax()]))
2.transform()
transform中傳入的函數只能返回兩種結果,可以廣播的標量值或者與分組大小相同的結果數組。
"對分組求均值,然後把這個最小值賦值給整個組(可廣播的標量值)"
print(g.transform(np.min))
"使用transform實現去最小值(返回與分組大小相同的結果數組)"
print(g.transform(lambda s:s-s.min()))
3.filter()-過濾
filter()對每個分組進行條件判斷。它將表示每個分組的DataFrame對象傳遞給回調函數,該函數返回True或False,以決定是否保留該分組。filter()的返回結果是過濾掉一些行之後的DataFrame對象,其行索引與源數據的行索引的順序一致。
4.apply()
apply會將分組傳遞給函數,然後嘗試將函數的返回結果組合起來。
df = DataFrame({'類別':['水果','水果','水果','蔬菜','蔬菜','肉類','肉類'],
'產地':['美國','中國','中國','中國','新西蘭','新西蘭','美國'],
'水果':['蘋果','梨','草莓','番茄','黃瓜','羊肉','牛肉'],
'數量':[5,5,9,3,2,10,8],
'價格':[5,5,10,3,3,13,20]})
print(df)
def get_rows(df,n=2): # 返回分組的前n行數據
return df.iloc[:n,:]
print(df.groupby('類別').apply(get_rows))
參考資源:https://blog.csdn.net/u012474716/article/details/81083895