Pandas滚动window计算最近n天相同项目的总和
Pandas Rolling window to calculate sum of the same items of the last n days
跟进 ,现在我想在滚动 window.
上给定相同分组的情况下计算不同列的 sum/mean
这是要设置的代码片段。我想计算每个人过去 30 天每行的收入sum/mean。另外,由于我的数据很大(实际数据有 170 万行),我认为任何使用 apply
的方法都行不通。
伪:
- 对于每一行,汇总来自
Date
的过去 30 天的数据
- 仅过滤相同
Name
的数据
- 计算
Earning
的 sum
和 return 行
d = {'Name': ['Jack', 'Jim', 'Jack', 'Jim', 'Jack', 'Jack', 'Jim', 'Jack', 'Jane', 'Jane'],
'Date': ['08/01/2021',
'27/01/2021',
'05/02/2021',
'10/02/2021',
'17/02/2021',
'18/02/2021',
'20/02/2021',
'21/02/2021',
'22/02/2021',
'29/03/2021'],
'Earning': [40, 10, 20, 20, 40, 50, 100, 70, 80, 90]}
df = pd.DataFrame(data=d)
df['Date'] = pd.to_datetime(df.Date, format='%d/%m/%Y')
df = df.sort_values('Date')
IIUC 使用
df = (df.join(df.set_index('Date')
.groupby('Name')['Earning']
.rolling('30d', closed='both')
.sum()
.rename('sum'), on=['Name', 'Date']))
print (df)
Name Date Earning sum
0 Jack 2021-01-08 40 40.0
1 Jim 2021-01-27 10 10.0
2 Jack 2021-02-05 20 60.0
3 Jim 2021-02-10 20 30.0
4 Jack 2021-02-17 40 60.0
5 Jack 2021-02-18 50 110.0
6 Jim 2021-02-20 100 130.0
7 Jack 2021-02-21 70 180.0
8 Jane 2021-02-22 80 80.0
9 Jane 2021-03-29 90 90.0
这个答案是基于@jezrael post 所以非常感谢你。不同的是这个解
- 使用左连接来确保我们不会改变原始数据的形状
- 过滤掉重复项,以防数据中存在相同的 ['Date'、'Name']。
def sum_of_last_n_days(df: pd.DataFrame, identifier: str, timestamp: str, sum_col: str, delta: int) -> pd.DataFrame:
col_name = "sum_%s" % identifier
temp_df = df.set_index(timestamp) \
.groupby(identifier, sort=False)[sum_col] \
.rolling('%sd' % delta, closed='both') \
.sum() \
.rename(col_name)
temp_df = temp_df[~temp_df.index.duplicated(keep="first")]
return df.merge(temp_df, how="left", left_on=[identifier, timestamp], right_index=True)
frequency_of_last_n_days(df, "Name", "Date", "Earning", 30)
结果
Name Date Earning sum
0 Jack 2021-01-08 40 40.0
1 Jim 2021-01-27 10 10.0
2 Jack 2021-02-05 20 60.0
3 Jim 2021-02-10 20 30.0
4 Jack 2021-02-17 40 60.0
5 Jack 2021-02-18 50 110.0
6 Jim 2021-02-20 100 130.0
7 Jack 2021-02-21 70 180.0
8 Jane 2021-02-22 80 80.0
9 Jane 2021-03-29 90 90.0
跟进
这是要设置的代码片段。我想计算每个人过去 30 天每行的收入sum/mean。另外,由于我的数据很大(实际数据有 170 万行),我认为任何使用 apply
的方法都行不通。
伪:
- 对于每一行,汇总来自
Date
的过去 30 天的数据
- 仅过滤相同
Name
的数据
- 计算
Earning
的sum
和 return 行
d = {'Name': ['Jack', 'Jim', 'Jack', 'Jim', 'Jack', 'Jack', 'Jim', 'Jack', 'Jane', 'Jane'],
'Date': ['08/01/2021',
'27/01/2021',
'05/02/2021',
'10/02/2021',
'17/02/2021',
'18/02/2021',
'20/02/2021',
'21/02/2021',
'22/02/2021',
'29/03/2021'],
'Earning': [40, 10, 20, 20, 40, 50, 100, 70, 80, 90]}
df = pd.DataFrame(data=d)
df['Date'] = pd.to_datetime(df.Date, format='%d/%m/%Y')
df = df.sort_values('Date')
IIUC 使用
df = (df.join(df.set_index('Date')
.groupby('Name')['Earning']
.rolling('30d', closed='both')
.sum()
.rename('sum'), on=['Name', 'Date']))
print (df)
Name Date Earning sum
0 Jack 2021-01-08 40 40.0
1 Jim 2021-01-27 10 10.0
2 Jack 2021-02-05 20 60.0
3 Jim 2021-02-10 20 30.0
4 Jack 2021-02-17 40 60.0
5 Jack 2021-02-18 50 110.0
6 Jim 2021-02-20 100 130.0
7 Jack 2021-02-21 70 180.0
8 Jane 2021-02-22 80 80.0
9 Jane 2021-03-29 90 90.0
这个答案是基于@jezrael post 所以非常感谢你。不同的是这个解
- 使用左连接来确保我们不会改变原始数据的形状
- 过滤掉重复项,以防数据中存在相同的 ['Date'、'Name']。
def sum_of_last_n_days(df: pd.DataFrame, identifier: str, timestamp: str, sum_col: str, delta: int) -> pd.DataFrame:
col_name = "sum_%s" % identifier
temp_df = df.set_index(timestamp) \
.groupby(identifier, sort=False)[sum_col] \
.rolling('%sd' % delta, closed='both') \
.sum() \
.rename(col_name)
temp_df = temp_df[~temp_df.index.duplicated(keep="first")]
return df.merge(temp_df, how="left", left_on=[identifier, timestamp], right_index=True)
frequency_of_last_n_days(df, "Name", "Date", "Earning", 30)
结果
Name Date Earning sum
0 Jack 2021-01-08 40 40.0
1 Jim 2021-01-27 10 10.0
2 Jack 2021-02-05 20 60.0
3 Jim 2021-02-10 20 30.0
4 Jack 2021-02-17 40 60.0
5 Jack 2021-02-18 50 110.0
6 Jim 2021-02-20 100 130.0
7 Jack 2021-02-21 70 180.0
8 Jane 2021-02-22 80 80.0
9 Jane 2021-03-29 90 90.0