文章目錄
- groupby()方法
- 通過列名進行分組
- 通過Series對象進行分組
- Series對象與原數據的行索引長度相等
- Series對象與原數據的行索引長度不等
- 通過字典進行分組
- 按照columns軸的方向進行分組
- 按照index軸的方向進行分組
- 通過函數進行分組
groupby()方法
groupby(
self,
by=None,
axis=0,
level=None,
as_index: bool = True,
sort: bool = True,
group_keys: bool = True,
squeeze: bool = False,
observed: bool = False,
)
部分參數表示的含義如下:
- by:用于確定進行分組的依據
- axis:表示分組軸的方向,可以為0或1,默認為0
- level:如果某個軸是一個MultiIndex對象(索引層次結構),則會按特定級別或多個級別分組
- as_index:表示聚合后的數據是否以組標簽作為索引的DataFrame對象輸出,接受布爾值,默認為True
- sort:表示是否對分組標簽進行排序,接受布爾值,默認為True
通過groupby()方法執行分組操作,會返回一個GroupBy對象,該對象實際上并沒有進行任何計算,只是包含一些而關于分組鍵的中間數據而已。
一般,使用Series調用groupby()方法返回的是SeriesGroupBy對象,而使用DataFrame調用groupby()方法返回的是DataFrameBy對象。
在進行分組時,通過指定by參數來確定分組標準,常用的分組方式主要有四種:
- 列表或數組,其長度必須與待分組的軸一樣
- DataFrame對象中某列的名稱
- 字典或Series對象,給出待分組軸上的值與分組名稱之間的對應關系
- 函數,用于處理軸索引或索引中的各個標簽
通過列名進行分組
代碼:
import numpy as np
import pandas as pddf = pd.DataFrame({"key": ['C', 'B', 'C', 'A', 'B', 'B', 'A', 'C', 'A'],"Data": [2, 4, 6, 8, 10, 1, 14, 16, 18]})
print(df)
group_obj = df.groupby(by='key')
print("df.groupby(by='key'):\n", group_obj)
輸出結果:
key Data
0 C 2
1 B 4
2 C 6
3 A 8
4 B 10
5 B 1
6 A 14
7 C 16
8 A 18
df.groupby(by='key'):<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002018919F2B0>
從輸出結果可以看出,DataFrame經過分組之后得到了一個DataFrameGroupBy對象,該對象是一個可迭代的對象,即只有在真正需要的時候才會執行計算(惰性計算)
如果要查看每個分組的具體內容,應該使用for循環遍歷DataFrameGroupBy對象。
代碼:
for i in group_obj:print(i)
輸出結果:
('A', key Data
3 A 8
6 A 14
8 A 18)
('B', key Data
1 B 4
4 B 10
5 B 1)
('C', key Data
0 C 2
2 C 6
7 C 16)
通過Series對象進行分組
Series對象與原數據的行索引長度相等
將Series對象傳給by參數,作為分組鍵拆分DataFrame對象
代碼:
df1 = pd.DataFrame({'key1': ['A', 'A', 'B', 'B', 'A'],'kye2': ['one', 'two', 'one', 'two', 'one'],'data1': [2, 3, 4, 6, 8],'data2': [3, 5, 6, 3, 7]})
print(df1)se = pd.Series(['a', 'b', 'c', 'a', 'b'])
group_obj1 = df1.groupby(by=se)
for i in group_obj1:print(i)
輸出結果:
key1 kye2 data1 data2
0 A one 2 3
1 A two 3 5
2 B one 4 6
3 B two 6 3
4 A one 8 7('a', key1 kye2 data1 data2
0 A one 2 3
3 B two 6 3)
('b', key1 kye2 data1 data2
1 A two 3 5
4 A one 8 7)
('c', key1 kye2 data1 data2
2 B one 4 6)
從輸出結果可以看出,se將df1對象分成a,b,c三組,其中索引0和3對應的兩行為a組數據,索引1和4對應的兩行為b組數據,索引2對應的一行為c組數據。
Series對象與原數據的行索引長度不等
代碼:
se1 = pd.Series(['a', 'b', 'a'])
group_obj2 = df1.groupby(se1)
for i in group_obj2:print("group_obj2:\n", i)
輸出結果:
('a', key1 kye2 data1 data2
0 A one 2 3
2 B one 4 6)
('b', key1 kye2 data1 data2
1 A two 3 5)
由于se1只有三行數據,所以它只需要對df對象的前三行數據進行分組,即第一行第三行分為一組,最后一行分為一組,而不會將全部的數據進行分組
通過字典進行分組
用字典對DataFrame進行分組時,需要確定軸的方向及字典中的映射關系,即字典中的鍵為列名,字典的值為自定義的分組名。
按照columns軸的方向進行分組
代碼:
df2 = DataFrame({'a': [1, 2, 4, 8, 3],'b': [9, 6, 3, 7, 5],'c': [2, 3, 4, 6, 8],'d': [3, 5, 6, 3, 7]})
mapping = {'a': '第一組', 'b': '第二組', 'c': '第三組', 'd': '第一組'}
print(df2)
by_columns = df2.groupby(by=mapping, axis=1)
print("by_columns:")
for i in by_columns:print(i)
輸出結果:
a b c d
0 1 9 2 3
1 2 6 3 5
2 4 3 4 6
3 8 7 6 3
4 3 5 8 7
by_columns:
('第一組', a d
0 1 3
1 2 5
2 4 6
3 8 3
4 3 7)
('第三組', c
0 2
1 3
2 4
3 6
4 8)
('第二組', b
0 9
1 6
2 3
3 7
4 5)
拆分df2時,將a列、d列數據映射到第一組;將b列映射到第二組,將d列數據映射到第三組。
按照index軸的方向進行分組
代碼
mapping1 = {0: '第一組', 1: '第二組', 2: '第三組', 3: '第二組', 4: '第一組'}
by_index = df2.groupby(mapping1, axis=0)
print("by_index:")
for i in by_index:print(i)
輸出結果:
by_index:
('第一組', a b c d
0 1 9 2 3
4 3 5 8 7)
('第三組', a b c d
2 4 3 4 6)
('第二組', a b c d
1 2 6 3 5
3 8 7 6 3)
拆分df2時,將0行、4行數據映射到第一組;將1行、3行映射到第二組,將2行數據映射到第三組。
通過函數進行分組
使用函數作為分組鍵會更加靈活,任何一個被當作分組鍵的函數都會在各個索引值上被調用一次,返回的值會被用作分組名稱。
代碼:
df2 = DataFrame({'a': [1, 2, 4, 8, 3],'b': [9, 6, 3, 7, 5],'c': [2, 3, 4, 6, 8],'d': [3, 5, 6, 3, 7]},index=['Bob', 'Alice', 'Job', 'Jack', 'Helen'])
group_obj3 = df2.groupby(by=len)
print("group_obj3")
for i in group_obj3:print(i)
輸出結果:
group_obj3
(3, a b c d
Bob 1 9 2 3
Job 4 3 4 6)
(4, a b c d
Jack 8 7 6 3)
(5, a b c d
Alice 2 6 3 5
Helen 3 5 8 7)
在調用groupby()方法時傳入了內置函數len(),表明len()函數會對行索引一列執行求長度的操作,以行索引名稱的長度進行分組,則長度相同的行索引名稱會分成一組。