Pandas分组累计求和

3

我奶奶有些奇怪的想法。每年生日她都带我去购物。

她有一些严格的规定。如果我买的礼物少于20美元,她就不会出任何钱。如果我花费超过20美元,她最多会出30美元。

所以,如果一个礼物价值27美元,她会出7美元。

这意味着我还剩下23美元来购买额外的礼物;任何附加礼物都适用上述相同的规则。

一旦花费了30美元,奶奶就不再提供任何贡献,我必须自己支付剩余部分的款项。

以下是我11岁、12岁和13岁生日的示例表格。

                         DollarsSpent  granny_pays
BirthDayAge PresentNum                           
11          1                  25.00         5.00   -- I used up $5
            2                 100.00        25.00   -- I used up last $20
            3                  10.00         0.00
            4                  50.00         0.00
12          1                  39.00        19.00  -- I used up $19 only $11 left
            2                   7.00         0.00
            3                  32.00        11.00  -- I used up the last $11 despite $12 of $32 above the $20 starting point
            4                  19.00         0.00
13          1                  21.00         1.00  -- used up $1
            2                  27.00         7.00  -- used up $7, total used up $8 and never spent last $22

那么在pandas中,我已经做到了这一步。

import pandas as pd
granny_wont_pay_first = 20.
granny_limit = 30.

df = pd.DataFrame({'BirthDayAge' : ['11','11','11','11','12','12','12','12','13','13']
                   ,'PresentNum' : [1,2,3,4,1,2,3,4,1,2]
                   ,'DollarsSpent' : [25.,100.,10.,50.,39.,7.,32.,19.,21.,27.]
              })

df.set_index(['BirthDayAge','PresentNum'],inplace=True)
df['granny_pays'] = df['DollarsSpent'] - granny_wont_pay_first
df['granny_limit'] = granny_limit
df['zero'] = 0.0
df['granny_pays'] =  df[['granny_pays','zero','granny_limit']].apply(np.median,axis=1)
df.drop(['granny_limit','zero'], axis=1, inplace=True)

print df.head(len(df))

以下是输出内容。使用3个数字的中位数是计算奶奶贡献的好方法。

问题在于每个礼物都被单独处理,我没有正确地减少每个生日年龄内的30美元。

                      DollarsSpent  granny_pays
BirthDayAge PresentNum                           
11          1                  25.00         5.00
            2                 100.00        30.00 -- should be 25.0
            3                  10.00         0.00
            4                  50.00        30.00 -- should be 0.0
12          1                  39.00        19.00
            2                   7.00         0.00
            3                  32.00        12.00 -- should be 11.0
            4                  19.00         0.00
13          1                  21.00         1.00
            2                  27.00         7.00

尝试想出一种优雅的pandas方法来进行腐蚀操作。

希望不要使用循环。

1个回答

4
我不确定是否有更简洁的方法,但这个应该可以工作,并且避免了请求中的循环。
df['per_gift'] = df.DollarsSpent - 20
df['per_gift'] = np.where( df.per_gift > 0, df.per_gift, 0 )

df['per_bday'] = df.groupby('BirthDayAge').per_gift.cumsum()
df['per_bday'] = np.where( df.per_bday > 30, 30, df.per_bday )

df['granny_pays'] = df.groupby('BirthDayAge').per_bday.diff()
df['granny_pays'] = df.granny_pays.fillna(df.per_bday)

请注意,'per_gift'忽略最高补贴金额为30美元的限制,而'per_bday'是每个“BirthDayAge”累积补贴(上限为30美元)。
  BirthDayAge  DollarsSpent  PresentNum  per_gift  per_bday  granny_pays
0          11            25           1         5         5            5
1          11           100           2        80        30           25
2          11            10           3         0        30            0
3          11            50           4        30        30            0
4          12            39           1        19        19           19
5          12             7           2         0        19            0
6          12            32           3        12        30           11
7          12            19           4         0        30            0
8          13            21           1         1         1            1
9          13            27           2         7         8            7

唉,我早已毕业很久了。 - Dickster
请参见:http://stackoverflow.com/questions/32358754/pandas-apply-transform-error-invalid-dtype-determination-in-get-concat-dt - Dickster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接