python - Pandas - 如果列中的值满足条件,则对前几行求和
问题描述
我有一个以下类型的数据框。除了我希望创建的最后一列“以前的总点数 P1”之外,我有所有列:
数据按“日期”列排序。
Date | Points_P1 | P1_id | P2_id | Total_Previous_Points_P1
-------------+---------------+----------+-----------------------------------
10/08/15 | 5 | 100 | 90 | 500
-------------+---------------+----------+-----------------------------------
11/09/16 | 5 | 100 | 90 | 500
-------------+---------------+----------+-----------------------------------
20/09/19 | 10 | 10000 | 360 | 4,200
-------------+---------------+----------+-----------------------------------
... | | ... | ... | ...
-------------+---------------+----------+-----------------------------------
n | | | |
现在我要创建的列是上面显示的“Total_Previous_Points_P1”列。
创建方式:
- 对于每一行,检查日期(称为 DATE_VAL)和 P1_id(称为 ID_VAL)
- 现在,对于 DATE_VAL AND 其中 P1 id == ID_VAL 之前的所有行,总结前面的点。
- 将此总和放在当前行的最后一列
有没有一种快速的 pandas pythonic 方法可以做到这一点?我的数据集非常大。
谢谢!
解决方案
SIA的解决方案计算Points_P1的总和,包括Points_P1 的当前值,而要求是对 先前的点求和(对于...之前的所有行)。
假设每个组中的日期都是唯一的(在您的示例中它们是唯一的),正确的pandasonic解决方案应包括以下步骤:
- 按日期排序。
- 按P1_id 分组,然后为每个组:
- 取Points_P1列。
- 计算累积总和。
- 减去Points_P1的当前值。
所以整个代码应该是:
df['Total_Previous_Points_P1'] = df.sort_values('Date')\
.groupby(['P1_id']).Points_P1.cumsum() - df.Points_P1
编辑
如果Date不是唯一的(在具有某些P1_id的行组内),则情况会更复杂,可以在此类源 DataFrame 上显示什么:
Date Points_P1 P1_id
0 2016-11-09 5 100
1 2016-11-09 3 100
2 2015-10-08 5 100
3 2019-09-20 10 10000
4 2019-09-21 7 100
5 2019-07-10 12 10000
6 2019-12-10 12 10000
请注意,对于P1_id有两行2016-11-09。
在这种情况下,从为每个P1_id和Date计算先前点的“组”总和开始:
sumPrev = df.groupby(['P1_id', 'Date']).Points_P1.sum()\
.groupby(level=0).apply(lambda gr: gr.shift(fill_value=0).cumsum())\
.rename('Total_Previous_Points_P1')
结果是:
P1_id Date
100 2015-10-08 0
2016-11-09 5
2019-09-21 13
10000 2019-07-10 0
2019-09-20 12
2019-12-10 22
Name: Total_Previous_Points_P1, dtype: int64
然后将df与P1_id和Date上的sumPrev合并(在索引上的sumPrev中):
df = pd.merge(df, sumPrev, left_on=['P1_id', 'Date'], right_index=True)
为了显示结果,在['P1_id', 'Date']上对df进行排序更有指导意义:
Date Points_P1 P1_id Total_Previous_Points_P1
2 2015-10-08 5 100 0
0 2016-11-09 5 100 5
1 2016-11-09 3 100 5
4 2019-09-21 7 100 13
5 2019-07-10 12 10000 0
3 2019-09-20 10 10000 12
6 2019-12-10 12 10000 22
如你看到的:
- 每个P1_id的第一个总和为0(没有来自先前日期的点)。
- 例如,对于Date == 2016-11-09的两行,先前点的总和为5(在Date == 2015-10-08的行中)。
推荐阅读
- raspbian - 未安装 Apache 配置文件
- sql - 使用 Pymssql 将数据插入 MS SQL DB 时出错
- java - 无法解决“清单合并失败:属性 application@appComponentFactory”
- r - r papaja::printnum(0L, numbers =F) 返回空值,而不是“零”
- javascript - 动态形式的价值转移错误信息
- python - 根据 YAML 1.1 规范,“是”真的是“真”的别名吗?1.2规范?
- c++ - 多项目解决方案中类导入的正确方法是什么
- arrays - 在其 didSet 中过滤数组
- python - 在 matplotlib 中绘图后隐藏线
- google-data-studio - 数据工作室:向计算指标输出添加符号