我有一个用户事件的熊猫数据框,按user_id和datetime升序排列。我想计算基于每个用户的事件之间的时间差,并且我希望每个用户在df['tdelta']
中的第一个事件记录都为空值。以下是快速操作,但是如果user_id更改,则不会使条目无效。
df['tdelta'] = df['time'] - df['time'].shift()
这是我当前的解决方案,但是太慢了。
def get_tdelta(df, tdelta_column="tdelta"):
df[tdelta_column] = np.NaN
df[tdelta_column] = df[tdelta_column].astype('datetime64[ns]')
for cid, pid, ct, pt, idx in zip(df['user_id'], df['user_id'].shift(), df['time'], df['time'].shift(), df.index):
if cid==pid:
df.loc[idx, tdelta_column] = ct - pt
else:
pass
return event_dataframe
event_df = get_tdelta(event_df)
我想有一个与以下类似的快速解决方案,但是我对如何完成它有些困惑。我已经添加了以下代码的错误,并且我理解为什么会得到它,但是我只是在寻找一种更快的方法来实现它
df['tdelta'] = df['time'] - df['time'].shift() if (df['user_id'] == df['user_id'].shift()) else np.NaN
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
以下是演示数据框前后的演示:
data = {'user_id' : [1, 1, 1, 2, 2, 2],
'event_id' : [2, 2, 3, 2, 3, 3],
'time' : ['2020-02-27 12:31:00', '2020-02-27 12:32:00', '2020-02-27 12:32:30', '2020-02-27 02:22:00', '2020-02-27 02:27:00', '2020-03-01 02:39:00']}
df = pd.DataFrame(data)
df.time = df.time.astype('datetime64[ns]')
user_id event_id time
0 1 2 2020-02-27 12:31:00
1 1 2 2020-02-27 12:32:00
2 1 3 2020-02-27 12:32:30
3 2 2 2020-02-27 02:22:00
4 2 3 2020-02-27 02:27:00
5 2 3 2020-03-01 02:39:00
data = {'user_id' : [1, 1, 1, 2, 2, 2],
'event_id' : [2, 2, 3, 2, 3, 3],
'time' : ['2020-02-27 12:31:00', '2020-02-27 12:32:00', '2020-02-27 12:32:30', '2020-02-27 02:22:00', '2020-02-27 02:27:00', '2020-03-01 02:39:00'],
'tdelta' : ['NaT', '0 days 00:01:00', '0 days 00:00:30', 'NaT', '0 days 00:05:00', '3 days 00:12:00']}
df = pd.DataFrame(data)
df.time = df.time.astype('datetime64[ns]')
user_id event_id time tdelta
0 1 2 2020-02-27 12:31:00 NaT
1 1 2 2020-02-27 12:32:00 0 days 00:01:00
2 1 3 2020-02-27 12:32:30 0 days 00:00:30
3 2 2 2020-02-27 02:22:00 NaT
4 2 3 2020-02-27 02:27:00 0 days 00:05:00
5 2 3 2020-03-01 02:39:00 3 days 00:12:00
答案 0 :(得分:0)
要计算每个用户的事件之间的时间增量,请按user_id
进行分组,然后对组合的数据帧应用移位减法。
然后,通过从索引中删除user_id
清理结果并作为新列分配回原始数据帧。每个user_id的第一个事件默认情况下为null (NaN)
。
df['tdelta'] = df.groupby('user_id') \
.apply(lambda x: x.time - x.time.shift()) \
.reset_index(level='user_id', drop=True)