R语言按用户分组基于双datetime列条件计数行数的实现
实现方案(基于Pandas)
核心逻辑是按用户分组后先按时序排序,判断相邻行的时间间隔打会话标签,最后按会话聚合统计行数即可,完整实现如下:
前置准备:导入依赖&格式兼容
import pandas as pd from datetime import datetime # 如果你的时间列是字符串/Unix时间戳格式,先统一转datetime格式 # df['starttimes'] = pd.to_datetime(df['starttimes']) # df['endtimes'] = pd.to_datetime(df['endtimes'])
第一步:构造模拟测试数据集(可跳过)
data = [ {"UserId": 1, "starttimes": datetime(2024,1,1,8,0), "endtimes": datetime(2024,1,1,8,30)}, {"UserId": 1, "starttimes": datetime(2024,1,1,8,40), "endtimes": datetime(2024,1,1,9,10)}, {"UserId": 1, "starttimes": datetime(2024,1,1,10,30), "endtimes": datetime(2024,1,1,11,0)}, {"UserId": 1, "starttimes": datetime(2024,1,1,11,10), "endtimes": datetime(2024,1,1,11,40)}, {"UserId": 2, "starttimes": datetime(2024,1,1,9,0), "endtimes": datetime(2024,1,1,9,20)}, {"UserId": 2, "starttimes": datetime(2024,1,1,11,0), "endtimes": datetime(2024,1,1,11,30)}, ] df = pd.DataFrame(data)
第二步:核心逻辑实现
# 1. 按用户+开始时间排序,保证时序正确 df = df.sort_values(["UserId", "starttimes"]).reset_index(drop=True) # 2. 计算当前行开始时间与上一行结束时间的差值(单位:小时) df['prev_end'] = df.groupby('UserId')['endtimes'].shift(1) df['time_diff_hour'] = (df['starttimes'] - df['prev_end']).dt.total_seconds() / 3600 # 3. 打会话标签:间隔≥1小时则开启新会话,标签逐次累加 df['new_session'] = (df['time_diff_hour'].fillna(0) >= 1).astype(int) df['session_id'] = df.groupby('UserId')['new_session'].cumsum() # 4. 按用户+会话分组统计区间内的行数 result = df.groupby(["UserId", "session_id"], as_index=False).size().rename(columns={"size": "row_count"})
结果验证
上述模拟数据运行后输出的result符合预期:
| UserId | session_id | row_count |
|---|---|---|
| 1 | 0 | 2 |
| 1 | 1 | 2 |
| 2 | 0 | 1 |
| 2 | 1 | 1 |
补充说明
- 不需要保留的中间字段(
prev_end/time_diff_hour/new_session/session_id)统计完成后可直接删除 - 如果是Unix时间戳格式,不需要转datetime,直接做差值后除以3600(秒级时间戳)或3600*1000(毫秒级时间戳)判断即可
- 单用户只有1行记录的边界情况已自动兼容,直接统计为1行
内容的提问来源于stack exchange,提问作者metaltoaster
相关产品推荐
相关产品推荐

