在Pandas时间序列中计数重复事件
我最近在学习基本的pandas库,但在当前的任务上遇到了一些困难:
我有一个(未规范化的)时间序列数据,里面每个时间戳都有一个用户ID。可以想象成这样: (日期, 用户ID, 负载)。就像一个服务器的日志文件,我想找出在特定时间段内有多少个IP地址是重复出现的。
现在我想知道有多少用户在某个时间段内有多个记录,比如说在4周内等等。所以这更像是一个滑动窗口,而不是在时间轴上固定的时间间隔。
我尝试的方法有:
- 根据用户ID重新索引df_users
- 或者使用多重索引?
可惜的是,我没有找到成功生成结果的方法。所以总的来说,我不确定如何用Pandas实现这种搜索,或者说用纯Python实现会不会更简单?还是我只是缺少了一些关键字来解决这个问题?
1 个回答
1
这里有一些我认为适合你问题的示例数据。
df = pd.DataFrame({'id': ['A','A','A','B','B','B','C','C','C'],
'time': ['2013-1-1', '2013-1-2', '2013-1-3',
'2013-1-1', '2013-1-5', '2013-1-7',
'2013-1-1', '2013-1-7', '2013-1-12']})
df['time'] = pd.to_datetime(df['time'])
这个方法需要有一个非空的数字列来进行计数,所以你可以添加一个虚拟的列。
df['dummy_numeric'] = 1
我解决这个问题的方法是这样的。首先,使用 groupby
按照用户 ID 分组,然后逐个处理每个用户的数据。接下来,使用 resample
将不规则的数据转换为每日的数据,这样就变得规范化了。
然后,使用 rolling_count
函数来计算每个 X 天窗口内的观察次数(这里用的是 3 天)。这样做是因为上采样后的数据会填充 NaN(缺失值),而这些缺失值不会被计入统计。注意,只有数字列被传递给 rolling_count
,而且要注意使用了双括号(这样会选择一个数据框而不是一个序列)。
window_days = 3
ids = []
for _, df_gb in df.groupby('id'):
df_gb = df_gb.set_index('time').resample('D')
df_gb = pd.rolling_count(df_gb[['dummy_numeric']], window_days).reset_index()
ids.append(df_gb)
把所有数据重新组合在一起,标记出观察次数超过某个值的区间。
df_stack = pd.concat(ids, ignore_index=True)
df_stack['multiple_requests'] = (df_stack['dummy_numeric'] > 1).astype(int)
然后再进行分组和求和,你就应该能得到正确的答案。
df_stack.groupby('time')['multiple_requests'].sum()
Out[356]:
time
2013-01-01 0
2013-01-02 1
2013-01-03 1
2013-01-04 0
2013-01-05 0
2013-01-06 0
2013-01-07 1
2013-01-08 0
2013-01-09 0
2013-01-10 0
2013-01-11 0
2013-01-12 0
Name: multiple, dtype: int32