【问题标题】:Sum a seprate colum based on the range of the dataframe between values in other columns after groupby根据 groupby 之后其他列中的值之间的数据框范围对单独的列求和
【发布时间】:2020-02-11 18:48:30
【问题描述】:

我有一个如下的数据框

id  Supply  days    days_180
1   30         0    180
1   100      183    363
1   80       250    430
2   5          0    180
2   5         10    190
3   5          0    180
3   30       100    280
3   30       150    330
3   30       200    380
3   30       280    460
3   50       310    490

我想对每行的“天数”和“天数+180”之间的天数求和。这需要在 groupby('id') 之后为每个组完成。

预期输出如下

id  Supply  days    days_180    use
1   30         0        180     30
1   100      183        363     180
1   80       250        430     80
2   5          0        180     10
2   5         10        190     10
3   5          0        180     65
3   30       100        280     120
3   30       150        330     140
3   30       200        380     110
3   30       280        460     80
3   50       310        490     50

我已经尝试了下面的代码,但它没有按预期工作。

df_d['use']=df_d.groupby('id').apply(lambda x: x.loc[x['days'].between(x['days'],x['days_180']),'supply'].sum())

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    使用列表理解循环每个组的每个 days_180 值,使用 sum 过滤并创建新列:

    def f(x):
        a = [x.loc[(x['days'] <= d) & (x['days_180'] >= d),'Supply'].sum() for d in x['days_180']]
        x['use'] = a
        return x
    

    或使用另一个 lambda 解决方案:

    def f(x):
        x['use'] = x['days_180'].apply(lambda d: x.loc[(x['days'] <= d) & 
                                                       (x['days_180'] >= d), 'Supply'].sum())
        return x
    
    
    df_d = df_d.groupby('id').apply(f)
    print (df_d)
        id  Supply  days  days_180  use
    0    1      30     0       180   30
    1    1     100   183       363  180
    2    1      80   250       430   80
    3    2       5     0       180   10
    4    2       5    10       190    5
    5    3       5     0       180   65
    6    3      30   100       280  120
    7    3      30   150       330  140
    8    3      30   200       380  110
    9    3      30   280       460   80
    10   3      50   310       490   50
    

    【讨论】:

    • 谢谢。我认为我们可以使用 lambda 函数来做到这一点,显然不行。
    • @moys - 欢迎您!也添加了带有 lambda 的解决方案。
    【解决方案2】:

    你也可以使用 numpy 的广播和 np.where 来做到这一点

    df.groupby("id").apply(
        lambda g: g.assign(use=(np.where((g.days.values>=g.days.values[:, np.newaxis]) & 
            (g.days.values<=g.days_180.values[:, np.newaxis]), g.Supply, 0).sum(axis=1)))
    ).reset_index(drop=True)
    

    jezrael 也可以像下面这样修改以在侧面应用中使用 lambda

    df = df.groupby('id').apply(lambda x:
        x.assign(use=[x.loc[(x['days'] <= d) & (x['days_180'] >= d),'Supply'].sum() for d in x['days_180']])
    )
    print (df)
    

    【讨论】:

      猜你喜欢
      • 2021-01-09
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      相关资源
      最近更新 更多