Pandas中的分組聚合功能其實類似SQL語句中的group by自己及聚合函數用法。具體地,Pandas中支持的分組主要有以下幾種形式。依次介紹如下:
1. 通過函數進行分組
pandas中可以通過定義函數對數據進行分組。
import pandas as pd
import numpy as np
def odd(num):
return (num%2)==0
data=pd.DataFrame(np.arange(21).reshape(3,7),columns=list('ABCDEFG'))
print("第一種分組結果:")
for key,group in data.groupby(odd):#相當於依據data的索引值在odd函數上的運行結果作爲分類標準
print(key)
print(group)
print("第二種分組結果:")
for key,group in data.groupby(odd(data['B'])):#相當於依據B列在odd函數的運行結果作爲分類標準
print(key)
print(group)
具體的代碼運行結果如下:
關於使用自定義對數據進行分組時,可以總結一下兩點:
- 首先,除了自定義的函數,python中的內建函數,比如len等,也可以直接用來進行分組。(此處並沒有舉例)
- 其次,這些函數不僅可以作用在索引列上,也可以自己指定作用列。
- 最後,指定了自定義函數的作用列之後,作用列中的每個值都會傳入到函數中執行。並根據其函數運行結果對原始數據進行分組。
2.在axis=1軸上進行分組
Pandas中使用groupby時默認是在axis=0軸上進行分組的,也可以通過設置在axis=1軸上進行分組。
import pandas as pd
import numpy as np
def odd(num):
return int(num)%2==0
data=pd.DataFrame(np.arange(20).reshape(4,5),index=list('1234'),columns=list('12345'))
print("原始數據:")
print(data)
data_axis0=data.groupby(odd,axis=0)#默認依據index在odd上的運行結果進行分組
print("按axis=0進行分組結果如下:")
for key,group in data_axis0:
print(key)
print(group)
data_axis1=data.groupby(odd,axis=1)#默認依據column在odd上的運行結果進行分組
print("按axis=1進行分組結果如下:")
for key,group in data_axis1:
print(key)
print(group)
代碼運行結果如下:
注意:
- pands中的兩種數據類型DataFrame和Series都支持GroupBy操作,但Series只支持在axis=0軸上進行操作。因爲Series沒有axis=1軸。
- 若未設置axis參數,默認按axis=0軸進行聚合。
3. 使用其他數據進行分組
前面介紹的對數據進行分組,主要是在兩類數據上進行的,一類是默認的index值或column值,還有一類就是dataframe中某一類或某一行的值。除了這兩類之外,pandas還可以依據非dataframe中的數據對dataframe進行分組。
import pandas as pd
import numpy as np
data=pd.DataFrame(np.arange(30).reshape(5,6),index=list('12345'),columns=list('ABCDEF'))
print(data)
date_list=[2004,2005,2006,2005,2004]
data_1=data.groupby(date_list)
print("分組結果如下:")
for key,group in data_1:
print(key)
print(group)
代碼運行結果如下:
注意:
- 首先,在這種寫法中不能設置axis參數(筆者是在python3.6版本進行的實驗)。原因暫且不明。
- 其次,從代碼運行結果進行反推可以得出以下兩個結論:1.聚合默認是在axis=0軸進行的。2.代碼中的date_list中的每個元素按照順序與dataframe中的記錄一一對應。所以date_list的長度要和dataframe中的記錄數一致。
除了使用上述List類型的數據作爲分組依據,還可以使用Series和字典作爲分組依據。下面僅以字典類型爲例:
import pandas as pd
import numpy as np
data=pd.DataFrame(np.arange(20).reshape(4,5),index=list('1234'),columns=list('12345'))
by_dict={'1':'red','2':'yellow','3':'yellow','4':'black','5':'white'}
by_dict1={'1':'red','2':'yellow','3':'yellow','5':'white'}
data_1=data.groupby(by_dict)
print("按by_dict分組的結果:")
for key,group in data_1:
print(key)
print(group)
data_2=data.groupby(by_dict1)
print("按by_dict1分組的結果:")
data_3=data.groupby(by_dict1)
for key,group in data_3:
print(key)
print(group)
代碼運行結果如下:
注意:
- 使用字典或Series作爲依據對數據進行分組時,如果行索引或列索引在分組依據(代碼中的by_dict和by_dict1變量)中並沒有找到對應關係,則對應的行或列是不參與最終的分組的(不是自成一組,可以從by_dict1分組的結果中看出此結論)。
- 分組依據中可以出現行索引或列索引中沒有出現的值。比如by_dict1中的5
- 使用Series和字典時,可以設置axis參數。
4.agg()或者aggregate()函數
Pandas和Series使用Groupby技術之後可以在得到的數據上進行一些數值型的聚合計算。通常的聚合方法包括以下幾種:
count(求數據量)、sum(求和)、mean(求均值)、median(求中位數)、std(求方差)、var(求標準差)、min(求最小值)、max(求最大值)、prod(求積)、first(求第一個值)、last(求最後一個值)。
以上這些聚合方法都會排除每個分組內的NaN值。當然也可以自定義聚合函數,但是自定義聚合函數的執行效率一般比較低。因爲以前在使用agg()函數的時候一直把握不準傳入聚合函數中的到底是什麼樣子的數據,所以每次使用自定義函數進行聚合的時候都會先將傳入聚合函數中的數據先print()輸出。
import pandas as pd
import numpy as np
df1=pd.DataFrame({
'Data1':np.random.randint(0,10,5),
'Data2':np.random.randint(10,20,5),
'key1':list("aabba"),
'key2':list('xyyxy')
})
def peak_range(df):
print(df)
return df.max()-df.min()
df1.groupby('key1').agg(peak_range)
首先我們先來看看傳送到聚合函數中的數據。從以下試驗結果中可以發現,聚合函數是按列接受每個groupby分組中的數據。
下面來看看聚合函數的運行結果,如下。