根据您的代码(您的groupby/apply),看起来(尽管您的示例......但也许我误解了您想要什么,然后安迪做了什么是最好的主意)您正在处理“约会” ' 列在您的实际数据中是 datetime64 dtype 而不是 integer dtype。此外,您似乎想要计算从给定group/stage 的第一次观察中测量的天数变化。我认为这是一组更好的示例数据(如果我正确理解您的目标):
>>> df
group date stage dur
0 A 2014-01-01 one 0
1 A 2014-01-03 one 2
2 A 2014-01-04 one 3
3 A 2014-01-05 two 0
4 B 2014-01-02 four 0
5 B 2014-01-06 five 0
6 B 2014-01-10 five 4
7 C 2014-01-03 two 0
8 C 2014-01-05 two 2
鉴于您应该通过在应用后以矢量化方式除以timedelta64 来修改您的应用(正如 Jeff 在他的评论中建议的那样)来加快速度(或者您可以在应用中进行) :
>>> df['dur'] = df.groupby(['group','stage']).date.apply(lambda x: x - x.iloc[0])
>>> df['dur'] /= np.timedelta64(1,'D')
>>> df
group date stage dur
0 A 2014-01-01 one 0
1 A 2014-01-03 one 2
2 A 2014-01-04 one 3
3 A 2014-01-05 two 0
4 B 2014-01-02 four 0
5 B 2014-01-06 five 0
6 B 2014-01-10 five 4
7 C 2014-01-03 two 0
8 C 2014-01-05 two 2
但您也可以避免使用groupby/apply,因为您的数据按组、阶段、日期顺序排列。每个['group','stage'] 分组的第一个日期发生在组更改或阶段更改时。所以我认为您可以执行以下操作:
>>> beg = (df.group != df.group.shift(1)) | (df.stage != df.stage.shift(1))
>>> df['dur'] = (df['date'] - df['date'].where(beg).ffill())/np.timedelta64(1,'D')
>>> df
group date stage dur
0 A 2014-01-01 one 0
1 A 2014-01-03 one 2
2 A 2014-01-04 one 3
3 A 2014-01-05 two 0
4 B 2014-01-02 four 0
5 B 2014-01-06 five 0
6 B 2014-01-10 five 4
7 C 2014-01-03 two 0
8 C 2014-01-05 two 2
说明:注意df['date'].where(beg) 创建的内容:
>>> beg = (df.group != df.group.shift(1)) | (df.stage != df.stage.shift(1))
>>> df['date'].where(beg)
0 2014-01-01
1 NaT
2 NaT
3 2014-01-05
4 2014-01-02
5 2014-01-06
6 NaT
7 2014-01-03
8 NaT
然后我 ffill 这些值并使用“日期”列取差值。
编辑:正如安迪指出的,你也可以使用transform:
>>> df['dur'] = df.date - df.groupby(['group','stage']).date.transform(lambda x: x.iloc[0])
>>> df['dur'] /= np.timedelta64(1,'D')
group date stage dur
0 A 2014-01-01 one 0
1 A 2014-01-03 one 2
2 A 2014-01-04 one 3
3 A 2014-01-05 two 0
4 B 2014-01-02 four 0
5 B 2014-01-06 five 0
6 B 2014-01-10 five 4
7 C 2014-01-03 two 0
8 C 2014-01-05 two 2
速度:我使用具有 400,000 次观察的相似数据框对这两种方法进行计时:
申请方法:
1 loops, best of 3: 18.3 s per loop
非申请方法:
1 loops, best of 3: 1.64 s per loop
所以我认为避免应用可以显着加快速度