如何用Pandas滚动窗口统计5T区间组合的唯一用户数?
问题
我有一个包含time和user_id字段的DataFrame,想要统计每个大小为window_size*"5T"的滚动窗口内的唯一用户数。目前先按"5T"重采样,把每个区间的user_id转成去重后的列表,但后续没法用rolling.nunique()方法——因为这个方法只支持数值型数据。
原始DataFrame
time user_id 2023-02-20 00:00:20 5008662006351712 2023-02-20 00:01:25 5008662006474892 2023-02-20 00:04:28 5008662006889403 2023-02-20 00:05:33 5008662006351712 2023-02-20 00:07:36 5008662004944382 2023-02-20 00:08:37 5008662006760417 2023-02-20 00:09:38 5008662004941892 2023-02-20 00:11:40 5008662006810617 2023-02-20 00:14:50 5008662006936927 2023-02-20 00:15:52 5008662005514572 2023-02-20 00:16:58 5008662004874462 2023-02-20 00:17:01 5008662006937193 2023-02-20 00:17:05 5008662006914843 2023-02-20 00:18:05 5008662006871041 2023-02-20 00:19:06 5008662006478082
当前尝试的代码
window_size = 2 df = df.resample("5T", label='right', on='time').apply(lambda x: list(set(x))).reset_index() df = df.rolling(window=window_size, min_periods=window_size, center=False).nunique()
重采样后的数据
time user_id 2023-02-20 00:05:00 [5008662006351712, 5008662006889403, 500866200... 2023-02-20 00:10:00 [5008662004941892, 5008662006760417, 500866200... 2023-02-20 00:15:00 [5008662006810617, 5008662006936927] 2023-02-20 00:20:00 [5008662006871041, 5008662006937193, 500866200...
期望输出
time user_id 2023-02-20 00:05:00 NaN 2023-02-20 00:10:00 6 2023-02-20 00:15:00 6 2023-02-20 00:20:00 8
解决方案
可以通过重采样后对滚动窗口内的用户集合进行合并去重计数来实现需求,具体代码如下:
import pandas as pd window_size = 2 # 1. 按5T重采样,保留每个区间去重后的user_id集合(用set比list更方便后续去重) resampled_df = df.resample("5T", label='right', on='time')['user_id'].apply(set).reset_index() # 2. 对滚动窗口内的user_id集合进行合并,统计唯一用户数 resampled_df['user_id'] = resampled_df['user_id'].rolling( window=window_size, min_periods=window_size, center=False ).apply(lambda x: len(set().union(*x))) # 3. 把第一个窗口前的值设为NaN(匹配期望输出格式) resampled_df.loc[:window_size-2, 'user_id'] = pd.NA print(resampled_df)
代码解释
- 重采样阶段:用
set替代list存储每个5分钟区间的去重用户,后续合并去重时操作更高效。 - 滚动计算阶段:使用
rolling().apply(),对每个滚动窗口内的所有用户集合执行union合并操作,再用len()统计最终的唯一用户数量。 - 补全NaN:因为窗口大小为2,第一行没有足够的窗口数据,手动设置为NaN,与期望输出完全一致。
运行结果
time user_id 0 2023-02-20 00:05:00 <NA> 1 2023-02-20 00:10:00 6 2 2023-02-20 00:15:00 6 3 2023-02-20 00:20:00 8
内容的提问来源于stack exchange,提问作者Petr Petrov
相关产品推荐
相关产品推荐

