Skip to content

Python Pandas - 聚合

Pandas 提供了强大的窗口操作,如 rolling()(滚动)、expanding()(扩展)和 ewm()(指数加权移动),以便对滑动或扩展的数据窗口执行计算。创建窗口对象后(例如 df.rolling(window=3)),可以对其应用各种聚合方法 (aggregation methods)。

我们创建一个带有时间序列索引 (time series index) 的 DataFrame,并演示在 rolling 窗口上进行聚合。

import pandas as pd
import numpy as np
rng = np.random.default_rng(42)
df = pd.DataFrame(rng.standard_normal((10, 4)),
index=pd.date_range('2023-01-01', periods=10, freq='D'),
columns=['A', 'B', 'C', 'D'])
print('Original DataFrame:')
print(df)
# Create a rolling window object
# window=3 means calculations consider the current row and the previous 2 rows.
# min_periods=1 means it will calculate even if the window has only 1 or 2 points (at the start).
rolling_window = df.rolling(window=3, min_periods=1)
# print('\n滚动窗口对象:')
# print(rolling_window)

示例输出:

Original DataFrame:
A B C D
2023-01-01 0.496714 -0.138264 0.647689 1.523030
2023-01-02 -0.234153 -0.234137 1.579213 0.767435
2023-01-03 -0.469474 0.542560 -0.463418 -0.465730
2023-01-04 0.241962 -1.913280 -1.724918 -0.562288
2023-01-05 -1.012831 0.314247 -0.908024 -1.412304
2023-01-06 1.465649 -0.225776 0.067528 -1.424748
2023-01-07 -0.544383 0.110923 -1.150994 0.375698
2023-01-08 -0.600639 -0.291694 -0.601707 1.852278
2023-01-09 -0.013497 -1.057711 0.822545 -1.220844
2023-01-10 0.208864 -1.150856 -1.347759 0.577046
Rolling Window Object:
Rolling [window=3,min_periods=1,center=False,axis=0,method=single]

现在,我们可以对这个 rolling_window 对象应用聚合函数,如 sum()、mean()、max()、min()、std() 等。.agg() 方法提供了应用一个或多个函数的灵活性。

你可以同时对所有列应用一个聚合函数(如 sum 或 mean)。

# 使用前面示例中的 df 和 rolling_window
# 计算 rolling sum
rolling_sum = rolling_window.sum()
print('\nRolling Sum (window=3):')
print(rolling_sum)
# 使用字符串别名 .agg() 的等效写法
rolling_sum_agg = rolling_window.agg('sum')
# print('\n使用 .agg("sum") 计算 rolling sum:')
# print(rolling_sum_agg)
# 计算 rolling mean
rolling_mean = rolling_window.mean()
print('\nRolling Mean (window=3):')
print(rolling_mean)
# 使用 NumPy 函数 .agg() 的等效写法
rolling_mean_agg = rolling_window.agg(np.mean)
# print('\n使用 .agg(np.mean) 计算 rolling mean:')
# print(rolling_mean_agg)

示例输出:

Rolling Sum (window=3):
A B C D
2023-01-01 0.496714 -0.138264 0.647689 1.523030
2023-01-02 0.262561 -0.372401 2.226902 2.290465
2023-01-03 -0.206913 0.170159 1.763483 1.824735
2023-01-04 -0.461665 -1.604857 -0.610123 -0.250583
2023-01-05 -1.240343 -1.056473 -3.096360 -2.440322
2023-01-06 0.694780 -1.824809 -2.565414 -3.399340
2023-01-07 -0.091565 0.199394 -1.991490 -2.461354
2023-01-08 0.320627 -0.406547 -1.685173 -0.196772
2023-01-09 -1.158519 -1.238482 -0.929156 1.007132
2023-01-10 -0.405272 -2.500261 -1.126921 1.208480
Rolling Mean (window=3):
A B C D
2023-01-01 0.496714 0.496714 0.647689 1.523030
2023-01-02 0.131280 0.131280 1.113451 1.145232
2023-01-03 -0.068971 -0.068971 0.587828 0.608245
2023-01-04 -0.153888 -0.153888 -0.203374 -0.083528
2023-01-05 -0.413448 -0.413448 -1.032120 -0.813441
2023-01-06 0.231593 0.231593 -0.855138 -1.133113
2023-01-07 -0.030522 -0.030522 -0.663830 -0.820451
2023-01-08 0.106876 0.106876 -0.561724 -0.065591
2023-01-09 -0.386173 -0.386173 -0.309719 0.335711
2023-01-10 -0.135091 -0.135091 -0.375640 0.402827

你可以 在 应用聚合 之前 选择一个特定的列。

# 使用第一个示例中的 df 和 rolling_window
# 仅计算列 'A' 的 rolling sum
rolling_sum_A = rolling_window['A'].sum()
print('\nRolling Sum for Column A:')
print(rolling_sum_A)
# 另一种方法:先选择列,然后应用 rolling
rolling_sum_A_alt = df['A'].rolling(window=3, min_periods=1).sum()
# print('\n列 A 的 rolling sum(另一种方法):')
# print(rolling_sum_A_alt)

示例输出:

Rolling Sum for Column A:
2023-01-01 0.496714
2023-01-02 0.262561
2023-01-03 -0.206913
2023-01-04 -0.461665
2023-01-05 -1.240343
2023-01-06 0.694780
2023-01-07 -0.091565
2023-01-08 0.320627
2023-01-09 -1.158519
2023-01-10 -0.405272
Freq: D, Name: A, dtype: float64

使用列表索引选择多个列。

# 使用第一个示例中的 df 和 rolling_window
# 计算列 'A' 和 'B' 的 rolling sum
rolling_sum_AB = rolling_window[['A', 'B']].sum()
print("\nRolling Sum for Columns 'A' and 'B':")
print(rolling_sum_AB)

示例输出:

Rolling Sum for Columns 'A' and 'B':
A B
2023-01-01 0.496714 -0.138264
2023-01-02 0.262561 -0.372401
2023-01-03 -0.206913 0.170159
2023-01-04 -0.461665 -1.604857
2023-01-05 -1.240343 -1.056473
2023-01-06 0.694780 -1.824809
2023-01-07 -0.091565 0.199394
2023-01-08 0.320627 -0.406547
2023-01-09 -1.158519 -1.238482
2023-01-10 -0.405272 -2.500261

使用 .agg() 方法,并传入一个函数名称(字符串)或可调用函数组成的列表。

# 使用第一个示例中的 df 和 rolling_window
# 计算列 'A' 的 rolling sum 和 mean
rolling_agg_A = rolling_window['A'].agg([np.sum, np.mean])
print("\nRolling Sum and Mean for Column 'A' (using NumPy functions):")
print(rolling_agg_A)
# 使用字符串别名
rolling_agg_A_str = rolling_window['A'].agg(['sum', 'mean'])
print("\n列 'A' 的 rolling sum 和 mean(使用字符串):")
print(rolling_agg_A_str)

示例输出:

Rolling Sum and Mean for Column 'A' (using NumPy functions):
sum mean
2023-01-01 0.496714 0.496714
2023-01-02 0.262561 0.131280
2023-01-03 -0.206913 -0.068971
2023-01-04 -0.461665 -0.153888
2023-01-05 -1.240343 -0.413448
2023-01-06 0.694780 0.231593
2023-01-07 -0.091565 -0.030522
2023-01-08 0.320627 0.106876
2023-01-09 -1.158519 -0.386173
2023-01-10 -0.405272 -0.135091
Rolling Sum and Mean for Column 'A' (using strings):
sum mean
2023-01-01 0.496714 0.496714
2023-01-02 0.262561 0.131280
2023-01-03 -0.206913 -0.068971
2023-01-04 -0.461665 -0.153888
2023-01-05 -1.240343 -0.413448
2023-01-06 0.694780 0.231593
2023-01-07 -0.091565 -0.030522
2023-01-08 0.320627 0.106876
2023-01-09 -1.158519 -0.386173
2023-01-10 -0.405272 -0.135091

将列选择与 .agg() 和函数列表结合使用。结果将具有列的 MultiIndex。

# 使用第一个示例中的 df 和 rolling_window
# 计算列 'A' 和 'B' 的 rolling sum 和 mean
rolling_agg_AB = rolling_window[['A', 'B']].agg(['sum', 'mean'])
print("\nRolling Sum and Mean for Columns 'A' and 'B':")
print(rolling_agg_AB)

示例输出:

Rolling Sum and Mean for Columns 'A' and 'B':
A B
sum mean sum mean
2023-01-01 0.496714 0.496714 -0.138264 -0.138264
2023-01-02 0.262561 0.131280 -0.372401 -0.186201
2023-01-03 -0.206913 -0.068971 0.170159 0.056720
2023-01-04 -0.461665 -0.153888 -1.604857 -0.534952
2023-01-05 -1.240343 -0.413448 -1.056473 -0.352158
2023-01-06 0.694780 0.231593 -1.824809 -1.133113
2023-01-07 -0.091565 -0.030522 0.199394 0.066465
2023-01-08 0.320627 0.106876 -0.406547 -0.135516
2023-01-09 -1.158519 -0.386173 -1.238482 -0.412827
2023-01-10 -0.405272 -0.135091 -2.500261 -0.833420

使用 .agg() 并传入一个字典,其中键是列名,值是应用于该列的一个或多个函数。

import pandas as pd
import numpy as np
rng = np.random.default_rng(43)
df_small = pd.DataFrame(rng.standard_normal((5, 4)),
index=pd.date_range('2023-01-01', periods=5, freq='D'),
columns=['A', 'B', 'C', 'D'])
print('Small DataFrame:')
print(df_small)
rolling_small = df_small.rolling(window=3, min_periods=1)
# 计算 'A' 的 rolling sum 和 'B' 的 rolling mean
rolling_diff_agg = rolling_small.agg({
'A': 'sum', # 对列 A 应用 sum
'B': np.mean # 对列 B 应用 mean
})
print("\nRolling Sum for 'A' and Rolling Mean for 'B':")
print(rolling_diff_agg)
# 对特定列应用多个函数
rolling_multi_diff_agg = rolling_small.agg({
'A': ['sum', 'std'],
'C': 'mean'
})
print("\n列 'A' 的 rolling sum/std 和列 'C' 的 rolling mean:")
print(rolling_multi_diff_agg)

示例输出:

Small DataFrame:
A B C D
2023-01-01 -0.535952 -0.875490 -0.269001 -0.087176
2023-01-02 0.125819 0.747178 -1.255743 -0.977989
2023-01-03 -1.034384 -0.977989 -0.375991 0.167076
2023-01-04 0.417561 -0.166471 0.674515 -1.179824
2023-01-05 -0.563337 -0.508814 -0.494112 -0.211489
Rolling Sum for 'A' and Rolling Mean for 'B':
A B
2023-01-01 -0.535952 -0.875490
2023-01-02 -0.410133 -0.064156
2023-01-03 -1.444517 -0.368767
2023-01-04 -0.491004 -0.132427
2023-01-05 -1.180160 -0.551091
Rolling Sum/Std for 'A' and Rolling Mean for 'C':
A C
sum std mean
2023-01-01 -0.535952 NaN -0.269001
2023-01-02 -0.410133 0.467941 -0.762372
2023-01-03 -1.444517 0.608989 -0.633578
2023-01-04 -0.491004 0.738906 -0.319073
2023-01-05 -1.180160 0.756068 0.068137