1. 程式人生 > 實用技巧 >pandas分組統計 - groupby詳解

pandas分組統計 - groupby詳解

資料分組

分組統計 - groupby功能

① 根據某些條件將資料拆分成組
② 對每個組獨立應用函式
③ 將結果合併到一個數據結構中

Dataframe在行(axis=0)或列(axis=1)上進行分組,將一個函式應用到各個分組併產生一個新值,然後函式執行結果被合併到最終的結果物件中。

df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

注:因為輸出結果冗長,請讀者自行賦值貼上到jupyter(推薦)中執行。歡迎評論交流

分組

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),
                   'D' : np.random.randn(8)})
print(df)
print('------')

print(df.groupby('A'), type(df.groupby('A')))
print('------')
# 直接分組得到一個groupby物件,是一箇中間資料,沒有進行計算

a = df.groupby('A').mean()
b = df.groupby(['A','B']).mean()
c = df.groupby(['A'])['D'].mean()  # 以A分組,算D的平均值
print("-----------------")
print(a,type(a),'\n',a.columns)
print()
print(b,type(b),'\n',b.columns)
print()
print(c,type(c))
# 通過分組後的計算,得到一個新的dataframe
# 預設axis = 0,以行來分組
# 可單個或多個([])列分組

  

分組 - 可迭代物件

df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
print(df)
print(df.groupby('X'), type(df.groupby('X')))
print('-----')

print(list(df.groupby('X')), '→ 可迭代物件,直接生成list\n')
print(list(df.groupby('X'))[0], '→ 以元祖形式顯示\n')
for n,g in df.groupby('X'):
    print(n)
    print(g)
    print('###')
print('-----')
# n是組名,g是分組後的Dataframe

print(df.groupby(['X']).get_group('A'),'\n')
print(df.groupby(['X']).get_group('B'),'\n')
print('-----')
# .get_group()提取分組後的組

grouped = df.groupby(['X'])
print(grouped.groups)
print(grouped.groups['A'])  # 也可寫:df.groupby('X').groups['A']
print('-----')
# .groups:將分組後的groups轉為dict
# 可以字典索引方法來檢視groups裡的元素

sz = grouped.size()
print(sz,type(sz))
print('-----')
# .size():檢視分組後的長度

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),
                   'D' : np.random.randn(8)})
print(df)
print()
print(df.groupby(['A','B']))
print()
grouped = df.groupby(['A','B']).groups

print(grouped)
print()
print(grouped[('foo', 'three')])
# 按照兩個列進行分組

  

其他軸上的分組

import pandas as pd
import numpy as np

df = pd.DataFrame({'data1':np.random.rand(2),
                  'data2':np.random.rand(2),
                  'key1':['a','b'],
                  'key2':['one','two']})
print(df)
print(df.dtypes)
print("-------------")
print(df.groupby(df.dtypes, axis=1))
print('-----')
print(list(df.groupby(df.dtypes, axis=1)))
print()
for n,p in df.groupby(df.dtypes, axis=1):
    print(n)
    print()
    print(p)
    print('##')
# 按照值型別分列

  

通過字典或者Series分組

df = pd.DataFrame(np.arange(16).reshape(4,4),
                  columns = ['a','b','c','d'])
print(df)
print('-----')

mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
by_column = df.groupby(mapping, axis = 1)
print(by_column.sum())
print('-----')
# mapping中,a、b列對應的為one,c、d列對應的為two,以字典來分組

s = pd.Series(mapping)
print(s,'\n')
print(s.groupby(s).count())
# s中,index中a、b對應的為one,c、d對應的為two,以Series來分組

  

通過函式分組

df = pd.DataFrame(np.arange(16).reshape(4,4),
                  columns = ['a','b','c','d'],
                 index = ['abc','bcd','aa','b'])
print(df,'\n')
print(df.groupby(len).sum())
# 按照字母長度分組

  

分組計算函式方法

s = pd.Series([1, 2, 3, 10, 20, 30], index = [1, 2, 3, 1, 2, 3])
grouped = s.groupby(level=0)  # 唯一索引用.groupby(level=0),將同一個index的分為一組
print(grouped)
print(grouped.first(),'→ first:非NaN的第一個值\n')
print(grouped.last(),'→ last:非NaN的最後一個值\n')
print(grouped.sum(),'→ sum:非NaN的和\n')
print(grouped.mean(),'→ mean:非NaN的平均值\n')
print(grouped.median(),'→ median:非NaN的算術中位數\n')
print(grouped.count(),'→ count:非NaN的值\n')
print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
print(grouped.std(),'→ std,var:非NaN的標準差和方差\n')
print(grouped.prod(),'→ prod:非NaN的積\n')

  

多函式計算:agg()

df = pd.DataFrame({'a':[1,1,2,2],
                  'b':np.random.rand(4),
                  'c':np.random.rand(4),
                  'd':np.random.rand(4),})
print(df)
print(df.groupby('a').agg(['mean',np.sum])) 
print(df.groupby('a')['b'].agg({'result1':np.mean,
                               'result2':np.sum}))
# 函式寫法可以用str,或者np.方法
# 可以通過list,dict傳入,當用dict時,key名為columns

  

下面是一個測試題,大家可以嘗試一下

按要求建立Dataframe df(如下圖),並通過分組得到以下結果
① 以A分組,求出C,D的分組平均值
② 以A,B分組,求出D,E的分組求和
③ 以A分組,得到所有分組,以字典顯示
④ 按照數值型別分組,求和
⑤ 將C,D作為一組分出來,並計算求和
⑥ 以B分組,求出每組的均值,求和,最大值,最小值

import pandas as pd
import numpy as np

df = pd.DataFrame({"A":["one","two","three","one","two","three","one","two"],
                  "B":(list("hhhh") + list("ffff")),
                   "C":range(10,26,2),
                   "D":np.random.randn(8),
                   "E":np.random.rand(8)
                  })
print(df)
print("----------以A分組,求出CD的分組平均值-------------")
print(df.groupby(["A"], axis = 0)["C","D"])
df1 = df.groupby(["A"], axis = 0)["C","D"].mean()   # 先聚合
print(df1)
print("-----------以AB分組,求DE的分組和--------")
df2 = df.groupby(["A", "B"], axis = 0)["D","E"].sum()   # 先聚合
print(df2)
print("-----------以A分組,得到所有分組的字典--------")
df2 = df.groupby(["A"], axis = 0)
print(df2.groups)
print("按照數值型別分組,求和")
df3 = df.groupby(df.dtypes, axis = 1).sum()
print(df3)
print("----------將CD作為一組分出來,並計算求和-----------")
mapping = {"C":"one", "D":"one"}
print(df.groupby(mapping, axis = 1).sum())
print("------------以B分組,求每一組的均值、和、最大值、最小值-----------------------------------------------------")
print(df.groupby(["B"]).agg([np.mean, np.sum, np.max, np.min]))