在Pandas时间序列中计数重复事件

0 投票
1 回答
861 浏览
提问于 2025-04-18 16:35

我最近在学习基本的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

撰写回答