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

如何用Pandas按月份计算登录时长?附DataFrame示例

Pandas处理登录登出时长按月统计解决方案

初始数据

IndexIDEventDatetime
11Login10.03.2023 12:00:00.000
21Logout05.04.2023 12:00:00.000
32Login20.04.2023 12:00:00.000
42Logout22.04.2023 12:00:00.000
51Login20.05.2023 12:00:00.000
61Login21.05.2023 12:00:00.000
71Logout22.05.2023 12:00:00.000
81Logout25.05.2023 12:00:00.000

目标结果

IDTimeInDaysMonth
121March
15April
16May
22April

实现方案

不需要拆分登录和登出DataFrame再合并,通过分组配对+时段拆分的方式即可完成需求,具体步骤如下:

1. 数据预处理

先将字符串类型的Datetime列转换为Pandas的datetime类型,并按ID和时间排序,保证记录的时间顺序:

import pandas as pd
from datetime import timedelta

# 构造初始DataFrame
data = {
    'Index': [1,2,3,4,5,6,7,8],
    'ID': [1,1,2,2,1,1,1,1],
    'Event': ['Login','Logout','Login','Logout','Login','Login','Logout','Logout'],
    'Datetime': ['10.03.2023 12:00:00.000','05.04.2023 12:00:00.000','20.04.2023 12:00:00.000','22.04.2023 12:00:00.000','20.05.2023 12:00:00.000','21.05.2023 12:00:00.000','22.05.2023 12:00:00.000','25.05.2023 12:00:00.000']
}
df = pd.DataFrame(data)

# 转换时间列格式
df['Datetime'] = pd.to_datetime(df['Datetime'], format='%d.%m.%Y %H:%M:%S.%f')

# 按ID和时间排序
df = df.sort_values(['ID', 'Datetime'])

2. 配对登录登出记录

给每个ID下的Login和Logout记录按顺序分配配对ID,确保第一个登录对应第一个登出、第二个登录对应第二个登出:

df['pair_id'] = df.groupby(['ID', 'Event']).cumcount()

# 透视得到配对的登录登出时间,过滤无配对的记录
pairs = df.pivot(index=['ID', 'pair_id'], columns='Event', values='Datetime').dropna()

3. 拆分跨月时段并计算时长

定义函数将单个登录-登出时段拆分为对应月份的时长,再对每个配对时段应用该函数:

def split_period_to_months(start, end):
    months = []
    current = start
    while current <= end:
        # 获取当月最后一天
        next_month = current + pd.DateOffset(months=1)
        month_end = next_month - pd.DateOffset(days=1)
        # 确定当月实际结束日期(不超过登出时间)
        actual_end = min(month_end, end)
        # 计算当月停留天数
        days = (actual_end - current).days
        months.append({
            'Month': current.strftime('%B'),
            'TimeInDays': days
        })
        current = next_month
    return pd.DataFrame(months)

# 处理所有配对时段
result_list = []
for (id_, pair_id), row in pairs.iterrows():
    period_df = split_period_to_months(row['Login'], row['Logout'])
    period_df['ID'] = id_
    result_list.append(period_df)

4. 汇总结果并整理格式

合并所有拆分后的时段数据,按ID和Month汇总时长,最后按时间顺序排序:

final_result = pd.concat(result_list).groupby(['ID', 'Month'], as_index=False)['TimeInDays'].sum()

# 按月份时间顺序排序(避免字母排序)
final_result['Month_num'] = pd.to_datetime(final_result['Month'], format='%B').dt.month
final_result = final_result.sort_values(['ID', 'Month_num']).drop('Month_num', axis=1).reset_index(drop=True)

print(final_result)

运行后即可得到目标格式的DataFrame。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 12:14:57