Python Pandas 數據分組 pd.groupby 的相關操作(二)shift, rolling, rank, cumsum, agg

數據準備

import pandas as pd
# 假設有 5 個人,分別參加了 4 門課程,獲得了對應的分數
# 同時這個 5 個人分別負責的項目個數 在 'Project_num' 列中顯示
data = {'name' : pd.Series(['Alice', 'Bob', 'Cathy', 'Dany', 'Ella', 'Ford', 'Gary', 'Ham', 'Ico', 'Jack']),
        'Math_A' : pd.Series([1.1, 2.2, 3.3, 4.4, 5, 3.2, 2.4, 1.5, 4.3, 4.5]),
        'English_A' : pd.Series([3, 2.6, 2, 1.7, 3, 3.3, 4.4, 5, 3.2, 2.4]),
        'Math_B' : pd.Series([1.7, 2.5, 3.6, 2.4, 5, 2.2, 3.3, 4.4, 1.5, 4.3]),
        'English_B' : pd.Series([5, 2.6, 2.4, 1.3, 3, 3.6, 2.4, 5, 2.2, 3.1]),
        'Project_num' : pd.Series([2, 3, 0, 1, 7, 2, 1, 5, 3, 4]),
        'Sex' : pd.Series(['F', 'M', 'M', 'F', 'M', 'F', 'M', 'M', 'F', 'M'])
     }
df = pd.DataFrame(data)
print(df)

運行結果:

    name  Math_A  English_A  Math_B  English_B  Project_num Sex
0  Alice     1.1        3.0     1.7        5.0            2   F
1    Bob     2.2        2.6     2.5        2.6            3   M
2  Cathy     3.3        2.0     3.6        2.4            0   M
3   Dany     4.4        1.7     2.4        1.3            1   F
4   Ella     5.0        3.0     5.0        3.0            7   M
5   Ford     3.2        3.3     2.2        3.6            2   F
6   Gary     2.4        4.4     3.3        2.4            1   M
7    Ham     1.5        5.0     4.4        5.0            5   M
8    Ico     4.3        3.2     1.5        2.2            3   F
9   Jack     4.5        2.4     4.3        3.1            4   M

一、數據平移 df.shift

1.1 上下平移

# 整個表上下移動(相當於在表第一行插入一空白行,但是最後一行由於沒有 index ,就消失了)
print(df.shift(1)) # 下移 1 行
print('\n')
print(df.shift(-2)) # 上移 2 行
print('\n')

運行結果:

    name  Math_A  English_A  Math_B  English_B  Project_num  Sex
0    NaN     NaN        NaN     NaN        NaN          NaN  NaN
1  Alice     1.1        3.0     1.7        5.0          2.0    F
2    Bob     2.2        2.6     2.5        2.6          3.0    M
3  Cathy     3.3        2.0     3.6        2.4          0.0    M
4   Dany     4.4        1.7     2.4        1.3          1.0    F
5   Ella     5.0        3.0     5.0        3.0          7.0    M
6   Ford     3.2        3.3     2.2        3.6          2.0    F
7   Gary     2.4        4.4     3.3        2.4          1.0    M
8    Ham     1.5        5.0     4.4        5.0          5.0    M
9    Ico     4.3        3.2     1.5        2.2          3.0    F


    name  Math_A  English_A  Math_B  English_B  Project_num  Sex
0  Cathy     3.3        2.0     3.6        2.4          0.0    M
1   Dany     4.4        1.7     2.4        1.3          1.0    F
2   Ella     5.0        3.0     5.0        3.0          7.0    M
3   Ford     3.2        3.3     2.2        3.6          2.0    F
4   Gary     2.4        4.4     3.3        2.4          1.0    M
5    Ham     1.5        5.0     4.4        5.0          5.0    M
6    Ico     4.3        3.2     1.5        2.2          3.0    F
7   Jack     4.5        2.4     4.3        3.1          4.0    M
8    NaN     NaN        NaN     NaN        NaN          NaN  NaN
9    NaN     NaN        NaN     NaN        NaN          NaN  NaN


1.2 左右平移

print(df.shift(1,axis=1)) # 右移 1 行,數據格式不兼容則顯示 NaN
print('\n')
print(df.shift(-2,axis=1)) # 左移 2 行,數據格式不兼容則顯示 NaN
print('\n')

運行結果:

  name  Math_A  English_A  Math_B  English_B  Project_num    Sex
0  NaN     NaN        1.1     3.0        1.7          NaN  Alice
1  NaN     NaN        2.2     2.6        2.5          NaN    Bob
2  NaN     NaN        3.3     2.0        3.6          NaN  Cathy
3  NaN     NaN        4.4     1.7        2.4          NaN   Dany
4  NaN     NaN        5.0     3.0        5.0          NaN   Ella
5  NaN     NaN        3.2     3.3        2.2          NaN   Ford
6  NaN     NaN        2.4     4.4        3.3          NaN   Gary
7  NaN     NaN        1.5     5.0        4.4          NaN    Ham
8  NaN     NaN        4.3     3.2        1.5          NaN    Ico
9  NaN     NaN        4.5     2.4        4.3          NaN   Jack


  name  Math_A  English_A  Math_B  English_B  Project_num  Sex
0  NaN     1.7        5.0     NaN        NaN          NaN  NaN
1  NaN     2.5        2.6     NaN        NaN          NaN  NaN
2  NaN     3.6        2.4     NaN        NaN          NaN  NaN
3  NaN     2.4        1.3     NaN        NaN          NaN  NaN
4  NaN     5.0        3.0     NaN        NaN          NaN  NaN
5  NaN     2.2        3.6     NaN        NaN          NaN  NaN
6  NaN     3.3        2.4     NaN        NaN          NaN  NaN
7  NaN     4.4        5.0     NaN        NaN          NaN  NaN
8  NaN     1.5        2.2     NaN        NaN          NaN  NaN
9  NaN     4.3        3.1     NaN        NaN          NaN  NaN


1.3 分組數據平移

for index,data in df.groupby(by='Sex'):
    print(index)
    print(data.shift(1))
    print('\n')

運行結果:

F
    name  Math_A  English_A  Math_B  English_B  Project_num  Sex
0    NaN     NaN        NaN     NaN        NaN          NaN  NaN
3  Alice     1.1        3.0     1.7        5.0          2.0    F
5   Dany     4.4        1.7     2.4        1.3          1.0    F
8   Ford     3.2        3.3     2.2        3.6          2.0    F


M
    name  Math_A  English_A  Math_B  English_B  Project_num  Sex
1    NaN     NaN        NaN     NaN        NaN          NaN  NaN
2    Bob     2.2        2.6     2.5        2.6          3.0    M
4  Cathy     3.3        2.0     3.6        2.4          0.0    M
6   Ella     5.0        3.0     5.0        3.0          7.0    M
7   Gary     2.4        4.4     3.3        2.4          1.0    M
9    Ham     1.5        5.0     4.4        5.0          5.0    M


二、數據滾動 df.rolling

2.1 滾動求和

print(df.rolling(window=3, min_periods=1, center=False, axis=0).sum())
# 這裏用一個長度爲 3 的窗口進行 從上往下 rolling ,每次移動一步,對每次窗口中覆蓋的數據進行求和
# 我們以此得到的值是 1.1, 1.1+2.2=3.3, 1.1+2.2+3.3=6.6, 2.2+3.3+4.4=9.9, 3.3+4.4+5=12.7~
# 這裏的 center 表示 是否從窗口的中心位置開始計算
# 即如果 center 取 True,我們得到的是 1.1+2.2=3.3, 1.1+2.2+3.3=6.6, 2.2+3.3+4.4=9.9~
print('\n')
# 應用舉例:比如我們想要滾動求過去 30 天內的總成交量

運行結果:

   Math_A  English_A  Math_B  English_B  Project_num
0     1.1        3.0     1.7        5.0          2.0
1     3.3        5.6     4.2        7.6          5.0
2     6.6        7.6     7.8       10.0          5.0
3     9.9        6.3     8.5        6.3          4.0
4    12.7        6.7    11.0        6.7          8.0
5    12.6        8.0     9.6        7.9         10.0
6    10.6       10.7    10.5        9.0         10.0
7     7.1       12.7     9.9       11.0          8.0
8     8.2       12.6     9.2        9.6          9.0
9    10.3       10.6    10.2       10.3         12.0

2.2 滾動求均值

print(df.groupby(['Sex'])['Project_num'].rolling(window=3).mean())
# 默認 min_periods = None,表示從窗口填滿開始,所以前面兩個值爲 NaN
# 這裏首先進行性別分組,然後從每個組中,以此取3個人,看平均負責的項目數量
print('\n')
# 其實在這個例子中使用沒什麼實際意義,通常實踐中時序數據用的比較多,比如求移動平均值

運行結果:

Sex   
F    0         NaN
     3         NaN
     5    1.666667
     8    2.000000
M    1         NaN
     2         NaN
     4    3.333333
     6    2.666667
     7    4.333333
     9    3.333333
Name: Project_num, dtype: float64

三、排名 df.rank

3.1 總排名

df_2 = df.set_index('name') # 將姓名提取爲 index
print(df_2)
print('\n')

for index, data in df_2.groupby(['Sex']):
    # 按照性別分組顯示
    print(index)
    print(data)
    print('\n')

df_3 = df_2.rank(ascending=False)
# 求 每個人 在 每一列中的綜合排名,這裏是從大到小排
# 並列排名會被取均值,比如 2 3 並列第2,則排名爲 2.5
print(df_3)
print('\n')

運行結果:

       Math_A  English_A  Math_B  English_B  Project_num Sex
name                                                        
Alice     1.1        3.0     1.7        5.0            2   F
Bob       2.2        2.6     2.5        2.6            3   M
Cathy     3.3        2.0     3.6        2.4            0   M
Dany      4.4        1.7     2.4        1.3            1   F
Ella      5.0        3.0     5.0        3.0            7   M
Ford      3.2        3.3     2.2        3.6            2   F
Gary      2.4        4.4     3.3        2.4            1   M
Ham       1.5        5.0     4.4        5.0            5   M
Ico       4.3        3.2     1.5        2.2            3   F
Jack      4.5        2.4     4.3        3.1            4   M


       Math_A  English_A  Math_B  English_B  Project_num  Sex
name                                                         
Alice    10.0        5.5     9.0        1.5          6.5  8.5
Bob       8.0        7.0     6.0        6.0          4.5  3.5
Cathy     5.0        9.0     4.0        7.5         10.0  3.5
Dany      3.0       10.0     7.0       10.0          8.5  8.5
Ella      1.0        5.5     1.0        5.0          1.0  3.5
Ford      6.0        3.0     8.0        3.0          6.5  8.5
Gary      7.0        2.0     5.0        7.5          8.5  3.5
Ham       9.0        1.0     2.0        1.5          2.0  3.5
Ico       4.0        4.0    10.0        9.0          4.5  8.5
Jack      2.0        8.0     3.0        4.0          3.0  3.5

3.1 分組後,針對某一列排名

for index, data in df_2.groupby(['Sex']):
    # 按照性別分組顯示
    print(index)
    print(data)
    print('\n')

df_4 = df_2.groupby(['Sex']).rank(ascending=False).sort_values('English_A')
# 按照性別分組後,求 每個人 在 每一組中的綜合排名(針對每一列),這裏是從大到小排
# 然後我們查看 按照 'English_A' 分數從高到底排列
print(df_4)
print('\n')

運行結果:

F
       Math_A  English_A  Math_B  English_B  Project_num Sex
name                                                        
Alice     1.1        3.0     1.7        5.0            2   F
Dany      4.4        1.7     2.4        1.3            1   F
Ford      3.2        3.3     2.2        3.6            2   F
Ico       4.3        3.2     1.5        2.2            3   F


M
       Math_A  English_A  Math_B  English_B  Project_num Sex
name                                                        
Bob       2.2        2.6     2.5        2.6            3   M
Cathy     3.3        2.0     3.6        2.4            0   M
Ella      5.0        3.0     5.0        3.0            7   M
Gary      2.4        4.4     3.3        2.4            1   M
Ham       1.5        5.0     4.4        5.0            5   M
Jack      4.5        2.4     4.3        3.1            4   M


       Math_A  English_A  Math_B  English_B  Project_num
name                                                    
Ford      3.0        1.0     2.0        2.0          2.5
Ham       6.0        1.0     2.0        1.0          2.0
Gary      4.0        2.0     5.0        5.5          5.0
Ico       2.0        2.0     4.0        3.0          1.0
Alice     4.0        3.0     3.0        1.0          2.5
Ella      1.0        3.0     1.0        3.0          1.0
Bob       5.0        4.0     6.0        4.0          4.0
Dany      1.0        4.0     1.0        4.0          4.0
Jack      2.0        5.0     3.0        2.0          3.0
Cathy     3.0        6.0     4.0        5.5          6.0

3.2 排名序號限定於 0~1 之間 ptc

df_5 = df_2['English_A'].rank(ascending=True, pct=True)
# 'ptc'表示把所有的排序序號限定在 0~1 的範圍內
# ascending=True 表示從小到大
print(df_5)
print('\n')

運行結果:

name
Alice    0.55
Bob      0.40
Cathy    0.20
Dany     0.10
Ella     0.55
Ford     0.80
Gary     0.90
Ham      1.00
Ico      0.70
Jack     0.30
Name: English_A, dtype: float64

3.3 排名方法 method=‘first’ / ‘min’ / ‘max’ / ‘dense’

df_6 = df_2['English_A'].rank(method='first',ascending=True)
# 雖然 Alice 和 Ella 都是 3 分,但是由於 Alice 的名字在原表格中先出現,在 method='first' 方法下,Alice排名在Ella前面
# method='min',看 Alice 和 Ella 這兩個名字的排序,A 小於 E,所以 Alice 排在 Ella 前面
# method='max',看 Alice 和 Ella 這兩個名字的排序,A 小於 E,所以 Ella 排在 Alice 前面
print(df_6)
print('\n')

df_6 = df_2['English_A'].rank(method='dense',ascending=True)
# 'dense' 方法下,Alice 和 Ella 並列第 5 ,後面從 6 開始繼續排名
# 所以這裏總的排名位數爲 9
print(df_6)
print('\n')

運行結果:

name
Alice     5.0
Bob       4.0
Cathy     2.0
Dany      1.0
Ella      6.0
Ford      8.0
Gary      9.0
Ham      10.0
Ico       7.0
Jack      3.0
Name: English_A, dtype: float64


name
Alice    5.0
Bob      4.0
Cathy    2.0
Dany     1.0
Ella     5.0
Ford     7.0
Gary     8.0
Ham      9.0
Ico      6.0
Jack     3.0
Name: English_A, dtype: float64

四、累計

4.1 累加 df.cumsum

print(df_2['Project_num'].cumsum())
# 挨個把每個人的項目數量加上去,看累計的總項目數量
print('\n')

運行結果:

name
Alice     2
Bob       5
Cathy     5
Dany      6
Ella     13
Ford     15
Gary     16
Ham      21
Ico      24
Jack     28
Name: Project_num, dtype: int64

4.2 累計迭代最大值/最小值 df.cummax / df.cummin

print(df_2['Project_num'].cummax())
# 挨個把每個人的項目數量對比,看最大值
print('\n')

print(df_2['Project_num'].cummin())
# 挨個把每個人的項目數量對比,看最小值
print('\n')

運行結果:

name
Alice    2
Bob      3
Cathy    3
Dany     3
Ella     7
Ford     7
Gary     7
Ham      7
Ico      7
Jack     7
Name: Project_num, dtype: int64


name
Alice    2
Bob      2
Cathy    0
Dany     0
Ella     0
Ford     0
Gary     0
Ham      0
Ico      0
Jack     0
Name: Project_num, dtype: int64

4.3 累乘 df.cumprod

print(df_2['Project_num'].cumprod())
# 累乘
print('\n')

運行結果:

name
Alice    2
Bob      6
Cathy    0
Dany     0
Ella     0
Ford     0
Gary     0
Ham      0
Ico      0
Jack     0
Name: Project_num, dtype: int64

五、聚合(作用於分組 df.groupby().agg)

5.1 針對單列聚合,並統計

df_agg = df_2.groupby('Sex')['Math_A'].agg(['min', 'mean', 'max'])
# 按照性別分組後,看每個組中 'Math_A' 的一些統計數據
print(df_agg)
print('\n')

運行結果:

     min  mean  max
Sex                
F    1.1  3.25  4.4
M    1.5  3.15  5.0

5.2 選取多列,並指定統計方法

agg_column = {'Math_A':['min','max'], 'Math_B':['max','mean']}
# 用字典選取多列,指定不同的統計方法
df_agg = df_2.groupby('Sex').agg(agg_column)
print(df_agg)
print('\n')

運行結果:

    Math_A      Math_B      
       min  max    max  mean
Sex                         
F      1.1  4.4    2.4  1.95
M      1.5  5.0    5.0  3.85
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章