对相同ID的第一行和最后一行之间的已排序数据帧进行操作

时间:2017-10-25 08:52:39

标签: python pandas dataframe

我有一个显示成员交易历史的数据框。

我已根据msnotransaction_date和' membership_expire_date'按升序对其进行排序。我希望生成一个新列,可以计算该成员与我们在一起的时间。例如,+++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=的成员执行2016-11-16至2017-02-15的交易。我可以用它们来计算月数。

任何更好的方法,而不是在整个行(大约数十万行)和for条件中执行if循环,以识别该特定成员的第一行和最后一行,然后执行减法交易日期?

 msno transaction_date membership_expire_date  payment_plan_days
6797850   +++FOrTS7ab3tIgIh8eWwX4FqRv8w/FoiOuyXsFvphY=       2016-09-09             2016-09-14                  5
1521480   +++IZseRRiQS9aaSkH6cMYU6bGDcxUieAi/tH67sC5s=       2015-11-21             2017-01-04                410
1498592   +++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=       2016-11-16             2016-12-15                 29
17923235  +++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=       2016-12-15             2017-01-15                 31
58566     +++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=       2017-01-15             2017-02-15                 31
1914756   +++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=       2017-02-15             2017-03-15                 28
7798380   +++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=       2015-01-31             2015-03-19                 47
14494860  +++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=       2015-02-28             2015-04-19                 50
11014601  +++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=       2015-03-31             2015-05-19                 49
13256589  +++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=       2015-04-30             2015-06-19                 50
18984021  +++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=       2015-05-31             2015-07-19                 49

2 个答案:

答案 0 :(得分:0)

扩展我的评论,使用sub + groupby

df.membership_expire_date.sub(df.transaction_date)\
                          .dt.days.groupby(df.msno).sum()

msno
+++FOrTS7ab3tIgIh8eWwX4FqRv8w/FoiOuyXsFvphY=      5
+++IZseRRiQS9aaSkH6cMYU6bGDcxUieAi/tH67sC5s=    410
+++hVY1rZox/33YtvDgmKA2Frg/2qhkz12B9ylCvh8o=    119
+++l/EXNMLTijfLBa8p2TUVVVp2aFGSuUI/h7mLmthw=    245

如果这些列不是datetime列,请在加载CSV时使用pd.to_datetimeparse_dates参数。

如果您要在现有数据框中添加新列,请使用transform + sum

s = df.membership_expire_date.sub(df.transaction_date)\
                    .dt.days.groupby(df.msno).transform('sum')    
s

6797850       5
1521480     410
1498592     119
17923235    119
58566       119
1914756     119
7798380     245
14494860    245
11014601    245
13256589    245
18984021    245
dtype: int64

df['diff'] = s

答案 1 :(得分:-1)

您可以做的是在数据框上设置一个键,这样您就可以查询每个msno

df_key = df.set_index(['msno'], validate=False)

msno = '+++FOrTS7ab3tIgIh8eWwX4FqRv8w/FoiOuyXsFvphY='

first_row = df_key[msno].iloc[0]
last_row = df_key[msno].iloc[-1]

然后你可以进行计算,例如

last_row['payment_plan_days'] - first_row['payment_plan_days']

如果你有一个完整的密钥,它可能更好地将它作为索引使用并执行validate = True,但这应该像魅力一样 - 并且你从pandas优化中受益,与循环不同