Pandas-如果列中的值满足条件,则对前一行求和

时间:2019-09-09 18:41:11

标签: python pandas dataframe

我有一个以下类型的数据框。除了最后一栏“ Total Previous Points 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之前且P1 id == ID_VAL的所有行,求和。
  • 将此金额放入当前行的最后一列

有没有一种快速的python方式来做到这一点?我的数据集很大。

谢谢!

2 个答案:

答案 0 :(得分:0)

尝试:

df['Total_Previous_Points_P1'] = df.groupby(['P1_id'])['Points_P1'].cumsum()

工作原理

首先,它使用P1_id功能对数据进行分组。

然后,它访问分组数据帧上的Points_P1值,并应用累积求和函数cumsum(),该函数将返回每个组的当前行(包括当前行)的点总和。

答案 1 :(得分:0)

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

编辑

如果日期不是唯一的(在具有某些 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 日期

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 的行中)。