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

如何计算DataFrame中每位玩家的每日游戏时长?

计算每位玩家的每日游戏时长(基于Pandas DataFrame)

问题背景

给定一个包含玩家ID(ids)和时间戳(ts)的Pandas DataFrame,记录了玩家的月度游戏行为,部分玩家ID存在重复。需要计算每位玩家的每日游戏总时长。

示例数据代码:

import pandas as pd

data  = {'ids':['Kelsier', 'Kelsier', 'Saze',
'Val','Kelsier','Val','Val','Val','Saze','Saze','Saze','Val'],
        'ts' : ["2022-12-21 18:29:59.141", "2022-12-21 19:02:59.141", '2022-12-21 10:12:23.545', '2022-12-19 11:15:20.612',  "2022-12-22 01:29:59.141",  "2022-12-22 05:26:48.151",  "2022-12-22 05:28:09.543",  "2022-12-22 05:30:14.522",  "2022-12-23 15:14:19.231",  "2022-12-24 10:14:39.601",  "2022-12-24 11:44:34.173", "2022-12-24 13:12:23.566"]}
df = pd.DataFrame(data)

df['ts'] = pd.to_datetime(df['ts'])

实现步骤

假设每条时间戳记录对应玩家的登录/登出交替行为(连续两条记录为一次游戏的开始和结束),具体实现如下:

1. 按玩家排序时间戳

先对每个玩家的时间戳按顺序排列,确保登录、登出记录的顺序正确:

# 按玩家分组并排序时间戳
df_sorted = df.groupby('ids')['ts'].apply(lambda x: x.sort_values()).reset_index(drop=True).to_frame()
df_sorted['ids'] = df.groupby('ids').groups.keys().repeat(df.groupby('ids').size())

2. 计算单次游戏时长

通过diff()方法计算相邻时间戳的差值,得到每次游戏的时长,并去除无效的NaN值(每个玩家的第一条记录没有前置时间戳):

# 计算相邻时间的差值(单次游戏时长)
df_sorted['duration'] = df_sorted.groupby('ids')['ts'].diff()

# 移除无时长的记录
df_sorted = df_sorted.dropna(subset=['duration'])

3. 关联游戏所属日期

将单次游戏时长关联到游戏开始的日期(即前置时间戳的日期):

# 提取游戏开始日期
df_sorted['date'] = df_sorted.groupby('ids')['ts'].shift().dt.date

4. 汇总每日总时长

按玩家ID和日期分组,求和得到每位玩家的每日总游戏时长,并可格式化时长为易读格式:

# 按玩家+日期汇总总时长
daily_duration = df_sorted.groupby(['ids', 'date'])['duration'].sum().reset_index()

# 格式化时长为 HH:MM:SS 格式
daily_duration['duration_formatted'] = daily_duration['duration'].astype(str).str.split('.').str[0]

最终结果

运行上述代码后,daily_duration即为所需统计结果,示例输出如下:

ids        date        duration duration_formatted
0   Kelsier  2022-12-21 0 days 00:33:00           00:33:00
1   Kelsier  2022-12-21 0 days 03:56:59           03:56:59
2      Saze  2022-12-21 0 days 00:00:00           00:00:00
3      Saze  2022-12-24 0 days 01:29:54           01:29:54
4       Val  2022-12-19 0 days 05:53:28           05:53:28
5       Val  2022-12-22 0 days 00:02:01           00:02:01
6       Val  2022-12-22 0 days 00:02:04           00:02:04
7       Val  2022-12-24 0 days 01:27:44           01:27:44

进阶处理:跨天游戏时长拆分

如果存在游戏跨天的情况(例如从23:50到次日00:10),需要将时长拆分到两个日期:

import numpy as np

def split_cross_day_duration(row):
    start_ts = row['start_ts']
    end_ts = row['ts']
    start_date = start_ts.date()
    end_date = end_ts.date()
    
    if start_date == end_date:
        return pd.Series([start_date, row['duration']])
    else:
        # 计算当天剩余时长
        end_of_day = pd.Timestamp(start_date) + pd.Timedelta(days=1)
        duration_day1 = end_of_day - start_ts
        duration_day2 = end_ts - end_of_day
        return pd.Series([start_date, duration_day1]), pd.Series([end_date, duration_day2])

# 先整理开始/结束时间对
df_sorted['start_ts'] = df_sorted.groupby('ids')['ts'].shift()
cross_day_processed = df_sorted.apply(split_cross_day_duration, axis=1).explode()
cross_day_processed = pd.DataFrame(cross_day_processed.tolist(), columns=['date', 'duration'])
cross_day_processed['ids'] = df_sorted['ids'].repeat(df_sorted.apply(lambda x: 2 if x['start_ts'].date() != x['ts'].date() else 1, axis=1)).values

# 重新汇总
daily_duration_cross = cross_day_processed.groupby(['ids', 'date'])['duration'].sum().reset_index()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:30:20