pandas 數據聚合與分組運算

目錄

一、分組

1.Groupby分組

2.對分組進行迭代 

3.通過字典或Series進行分組

 4.通過函數進行分組

5.根據索引級別分組

 二、聚合

 1.agg()聚合

2.transform()

3.filter()-過濾

4.apply()


一、分組

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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章