python - 根据 ID 和月份聚合数据,具体取决于另一列(前与后)
问题描述
假设 python 中的以下数据框,我如何检查每个名称的pre_hit_price和post_hit_price(平均值或总和)?
(在 SAS 中,我们可以使用 first. and last. 来解决这个问题)
d = {'Name': ['A','A','A','A','B','B','B','B'], 'price' : [0,1,2,3,2,4,6,8] , 'month': [201901, 201902, 201903, 201904, 201901, 201902, 201903, 201904] , 'hit': [0,1,0,0,0,1,1,0]}
df = pd.DataFrame(data=d)
df
示例_df:
- 这个名字在几个月内重复
- 命中列是差异化因素
- pre_hit_price对于 A 应为 0,对于 B 应为 2
- 对于 A, post_hit_price应为 (1+2+3),对于 B,应为 (4+6+8)。(包括命中月份)
输出_df:
解决方案
方法一
使用GroupBy.sum
+ DataFrame.unstack
。将布尔级数归为组 ( groupby_hit
) 的方法在方法 2中进行了说明。你只需要添加使用Series.map
groupby_hit=df.groupby('Name').hit.cumsum().eq(0).map({False:'post_hit_price',True:'pre_hit_price'})
new_df=df.groupby(['Name',groupby_hit],sort=False).price.sum().unstack().rename_axis(columns=None)
print(new_df)
pre_hit_price post_hit_price
Name
A 0 6
B 2 18
方法二
根据列中的外观和使用with1
的列hit
值创建两个 DataFrame以执行 a (请参阅详细信息)。然后使用+ :Name
DataFrame.groupby.cumsum
Series.eq
boolean indexing
Groupby.agg
pd.concat
prehit_mask=df.groupby('Name').hit.cumsum().eq(0)
df_pre=df[prehit_mask]
df_post=df[~prehit_mask]
new_df=pd.concat([df_pre.groupby('Name').price.agg(pre_hit_price='sum'),
df_post.groupby('Name').price.agg(post_hit_price='sum')],
axis=1)
print(new_df)
pre_hit_price post_hit_price
Name
A 0 6
B 2 18
如果您使用熊猫 <0.25.0:
new_df=pd.concat([df_pre.groupby('Name').price.agg({'pre_hit_price':'sum'}),
df_post.groupby('Name').price.agg({'post_hit_price':'sum'})],
axis=1)
细节:
print(prehit_mask)
0 True
1 False
2 False
3 False
4 True
5 False
6 False
7 False
Name: hit, dtype: bool
推荐阅读
- javascript - 刷新前在 Chrome 控制台中不可见的脚本,适用于 Firefox
- javascript - 通过参数传递从 Javascript 调用 C# 服务器端
- python - BeautifulSoup 循环没有遍历其他节点
- python - 查询表的多对多字段值
- python - 如何在熊猫的多列中对数据集进行分组
- java - 试图在一个单独的线程中运行一段代码
- php - Laravel 5.5:从模型中过滤查询
- java - Android 意图:是否有可能以适当的方式获得对手机存储中实际文件的引用?
- java - 在 ExecutorService 线程中运行 Http Server 或无限持续时间的任务好不好
- laravel - 如何为管理员、用户和父母进行多重身份验证。有谁能够帮我