我有一个数据帧,我想在其中将2列分组,从每组的第3列的奇数行中减去偶数,然后将结果分配给原始数据帧中的一列。我尝试从其他答案中尝试的任何方法似乎都对我没有帮助。
示例数据框:
ID Day OtherInfo log_timestamp
A 17 foo t1
A 17 bar t2
A 18 footoo t3
A 18 bar_bar t4
其中log_timestamp是日期时间对象。
我想要的结果应类似于:
ID Day OtherInfo log_timestamp duration
A 17 foo t1 (t2-t1)
A 17 bar t2
A 18 footoo t3 (t4-t3)
A 18 bar_bar t4
[我尝试了定义自己的函数,使用lambda函数以及使用“ apply”,“ agg”,“ map”和“ transform”的组合,但并不太了解。
>>>my_df['duration'] = my_df.groupby(['ID', 'day'])['log_timestamp'].agg({'duration': lambda series: (series - series.shift())[1::2].reset_index(drop=True)})
TypeError: incompatible index of inserted column with frame index
>>>my_df['duration'] = my_df['day'].map(my_df.groupby(['ID', 'day'])['log_timestamp'].apply({'duration': lambda series: (series - series.shift())[1::2].reset_index(drop=True)}))
TypeError: unhashable type: 'dict'
>>>my_df['duration'] = my_df.groupby(['ID', 'day'])['log_timestamp'].transform(lambda series: (series - series.shift())[1::2].reset_index(drop=True))
ValueError: Length of passed values is 1, index implies 2
我使用了Followitg测试DataFrame(带有“ true”时间戳):
ID Day OtherInfo log_timestamp
0 A 17 foo 2019-09-01 10:20:00
1 A 17 bar 2019-09-01 11:30:00
2 A 18 footoo 2019-09-01 15:10:00
3 A 18 bar_bar 2019-09-01 15:55:00
[从定义一个计算2个结果值的函数开始从两个源值(时间戳):
def fn(grp):
return [grp.iloc[1] - grp.iloc[0], np.nan]
第一个返回的值是差,第二个返回的是-NaN。
以下列方式使用它:
df['duration'] = df.groupby(np.arange(len(df.index)) // 2)\
.log_timestamp.transform(fn)
结果是:
ID Day OtherInfo log_timestamp duration
0 A 17 foo 2019-09-01 10:20:00 01:10:00
1 A 17 bar 2019-09-01 11:30:00 NaT
2 A 18 footoo 2019-09-01 15:10:00 00:45:00
3 A 18 bar_bar 2019-09-01 15:55:00 NaT
groupby(np.arange(len(df.index))// 2)是熊猫的“成语”按2行(或元素)将DataFrame(或Series)分组。
然后transform(fn)
生成一个值序列,类似于原始序列的“副本”(一对时间戳)。因此,第一个返回值-两个时间戳之间的差-是第一个元素的新值,第二个元素的NaN
-。因为目标列是Timestamp
类型,所以NaN是转换为NaT。