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

Python计算客户每日在线时长无法获取指定范围全量日期数据问题

问题排查

原有代码存在以下几处核心问题,导致无法输出指定日期范围内的所有在线时长记录:

  • 循环内未重置临时DataFrame:train__df定义在循环外,每次迭代没有清空重建,上一个客户的ping数据会残留,引发日期统计错误
  • 仅统计有ping记录的日期:当前的unique_dates是从用户实际产生ping的日期中去重得到的,用户当天未上线(无ping记录)的日期不会出现在结果中,自然无法覆盖2017年6月1日到21日的全日期范围
  • 无数据用户的判断逻辑错误:如果某客户完全没有ping记录,train__df['timestamp']是空序列,取索引0的操作会直接抛出索引越界错误
  • 废弃API性能问题:pandas的append方法已废弃,逐行追加DataFrame效率极低,数据量大时性能会非常差

修复后实现代码

import pandas as pd
import datetime
import math

# 定义目标统计日期范围
START_DATE = datetime.date(2017, 6, 1)
END_DATE = datetime.date(2017, 6, 21)
# 生成全量目标日期列表,格式和后续数据对齐
ALL_TARGET_DATES = [d.strftime('%Y-%m-%d') for d in pd.date_range(START_DATE, END_DATE)]

final_train_list = [] # 用列表暂存结果,最后一次性转DataFrame,性能更高
excluded_cust_ids = []

for index, cust_id in enumerate(customer_data['id'][:10].values.tolist()):
    print(f'Started for CustID {cust_id} count is {index}')
    # 拉取当前客户的所有ping记录
    cust_pings = pings_data.loc[pings_data['id'] == cust_id, "timestamp"].reset_index(drop=True)
    # 判断客户是否完全无有效ping记录
    if len(cust_pings) == 0 or math.isnan(cust_pings.iloc[0]):
        excluded_cust_ids.append(cust_id)
        # 无任何记录的客户,所有日期时长填0,不需要可以删除下面的循环
        for dt in ALL_TARGET_DATES:
            final_train_list.append({'id': cust_id, 'date': dt, 'hours': 0.0})
        continue
    # 处理当前客户的ping数据
    train_df = pd.DataFrame()
    train_df['timestamp'] = cust_pings
    train_df['date'] = cust_pings.apply(lambda ts: datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d'))
    train_df['time'] = cust_pings.apply(lambda ts: datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S'))
    # 打印当前客户有数据的唯一日期
    unique_active_dates = pd.unique(train_df['date']).tolist()
    print(unique_active_dates)
    # 遍历所有目标日期,计算对应时长
    for dt in ALL_TARGET_DATES:
        if dt not in unique_active_dates:
            # 当天无上线记录,时长记为0
            final_train_list.append({'id': cust_id, 'date': dt, 'hours': 0.0})
            continue
        # 当天有上线记录,计算当日在线时长
        day_pings = train_df.loc[train_df['date'] == dt].sort_values(by='time')
        start_time = pd.to_datetime(day_pings['time'].iloc[0])
        end_time = pd.to_datetime(day_pings['time'].iloc[-1])
        diff_hours = round((pd.Timedelta(end_time - start_time).seconds / 3600), 1)
        final_train_list.append({'id': cust_id, 'date': dt, 'hours': diff_hours})

# 批量转成最终DataFrame
final_train_df = pd.DataFrame(final_train_list)
print(final_train_df)
print(excluded_cust_ids)

final_train_df.to_excel("Final_train_df_excluding_cust_ids.xlsx", index=False)
print("completed for all customers except for non-active customers")

补充说明

当前代码沿用了你原有逻辑,用当日首次ping到末次ping的间隔作为在线时长。如果需要统计实际连续在线时长,可在计算时增加相邻ping的间隔判断,间隔小于阈值(比如5分钟)才计入在线时长,累加得到更准确的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 14:45:00