You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas实现指定日期范围的用户登录活跃总时长计算

实现方案

核心逻辑是先按用户+自然日聚合单日活跃窗口,再通过日期边界筛选统计总时长,完全适配你提到的所有自定义范围统计需求。

步骤1:预处理聚合单日活跃数据

你的样例数据中,同一用户同一天的多条事件对应当日一段连续活跃时段,因此先分组取当日最早、最晚事件时间作为活跃窗口的起止点,计算当日活跃时长:

import pandas as pd

# 完成基础时间字段转换
df['datetime'] = pd.to_datetime(df['start_time'], unit='s')
# 提取自然日维度用于分组
df['day'] = df['datetime'].dt.date

# 聚合得到每个用户单日的活跃窗口
daily_active = df.groupby(['id', 'day']).agg(
    active_start=('datetime', 'min'),
    active_end=('datetime', 'max')
).reset_index()
# 计算当日活跃时长(单位:秒)
daily_active['duration_sec'] = (daily_active['active_end'] - daily_active['active_start']).dt.total_seconds()

步骤2:封装通用范围统计函数

支持传入任意起始/结束日期,可灵活配置是否包含边界日期,直接返回总活跃时长:

def calc_total_active(start_date=None, end_date=None, include_start=True, include_end=True):
    """
    统计指定日期范围内的全用户活跃总时长
    参数说明:
    - start_date: 范围起始日期,支持字符串/date/datetime类型,传None代表不限制起始时间
    - end_date: 范围结束日期,支持字符串/date/datetime类型,传None代表不限制结束时间
    - include_start: 统计范围是否包含起始日期当天,默认True
    - include_end: 统计范围是否包含结束日期当天,默认True
    """
    filter_cond = pd.Series(True, index=daily_active.index)
    
    # 拼接起始时间过滤条件
    if start_date is not None:
        start = pd.to_datetime(start_date).date()
        filter_cond &= (daily_active['day'] >= start) if include_start else (daily_active['day'] > start)
    
    # 拼接结束时间过滤条件
    if end_date is not None:
        end = pd.to_datetime(end_date).date()
        filter_cond &= (daily_active['day'] <= end) if include_end else (daily_active['day'] < end)
    
    # 汇总符合条件的总时长
    total_seconds = daily_active.loc[filter_cond, 'duration_sec'].sum()
    return pd.Timedelta(seconds=total_seconds)

场景验证

你提到的几个统计场景可以直接调用函数得到正确结果:

  • 统计2016-03-31之前的活跃总时长:calc_total_active(end_date='2016-03-31', include_end=False),返回0 days 01:13:00,即1小时13分钟
  • 统计截至2016-04-02的活跃总时长:calc_total_active(end_date='2016-04-02'),返回0 days 02:15:00,即2小时15分钟
  • 统计2016-04-01至2016-04-10区间活跃总时长:calc_total_active(start_date='2016-04-01', end_date='2016-04-10'),返回0 days 01:43:00,即1小时43分钟

补充说明

  • 如果需要格式化输出X小时Y分钟的可读格式,可以加一个简单的转换函数:
def format_duration(td):
    total_min = int(td.total_seconds() // 60)
    hour = total_min // 60
    minute = total_min % 60
    return f"{hour}小时{minute}分钟"

# 用法示例
print(format_duration(calc_total_active(end_date='2016-04-02'))) # 输出:2小时15分钟
  • 如果需要按用户维度分别统计时长,只需要在过滤后的数据上按id分组求和即可,核心逻辑无需调整。
  • 如果后续存在跨天活跃的场景(比如用户活跃从23点持续到次日1点),只需要把分组逻辑替换为连续会话切分,再计算会话和统计日期范围的重叠时长即可,当前方案是匹配你现有数据特征的最简实现。

内容的提问来源于stack exchange,提问作者arilwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:21:30