利用Pandas按日期过滤DataFrame,统计流媒体各节目观看量
我来帮你搞定这个流媒体节目观看人数统计的需求,咱们一步步拆解来做:
步骤1:修正并格式化两个DataFrame的加载与时间处理
首先得提醒你,你加载programs_start_time的代码有点小问题——pd.DataFrame.from_dict()不能直接传JSON文件路径,得先把JSON内容读进来才行。另外,日志里的time只有时分秒,必须和节目日期(2019-05-29)拼接成完整的datetime,不然没法和节目的完整时间戳匹配。
完整的加载和时间格式化代码如下:
import pandas as pd import json # 处理日志数据:拼接完整日期+转换为datetime类型 viewers_from_log = pd.read_json('sqllog.json', encoding='UTF-8') # 日志时间属于节目当天,拼接日期得到完整时间戳 viewers_from_log['full_time'] = pd.to_datetime('2019-05-29 ' + viewers_from_log['time']) # 处理节目数据:先读取JSON文件,再转换为DataFrame with open('programs.json', 'r', encoding='UTF-8') as f: programs_data = json.load(f) # 提取目标日期的节目列表 programs_list = programs_data['2019-05-29'] programs_start_time = pd.DataFrame(programs_list) # 转换节目开始时间为datetime,同时移除UTC时区标记(和日志时间保持一致的无时区格式) programs_start_time['startTime_dt'] = pd.to_datetime(programs_start_time['startTime_dt']).dt.tz_localize(None)
步骤2:将日志条目与对应节目匹配
这里用pd.merge_asof是最便捷的方案——它会按时间顺序,把每条日志匹配到最近的、时间不晚于日志时间的节目(也就是这条日志属于该节目播放时段)。不过要注意,两个DataFrame都得先按时间排序:
# 对两个DataFrame按时间排序,满足merge_asof的要求 viewers_from_log_sorted = viewers_from_log.sort_values('full_time') programs_sorted = programs_start_time.sort_values('startTime_dt') # 执行时间匹配,把日志和对应节目关联起来 matched_data = pd.merge_asof( viewers_from_log_sorted, programs_sorted, left_on='full_time', right_on='startTime_dt', direction='backward' # 规则:找最近的、早于当前日志时间的节目开始时间 )
如果日志里有早于第一个节目开始时间的条目(比如你的示例里0:00:17、0:00:26早于第一个节目0:00:40),这些条目会被匹配到NaN,你可以根据需求单独处理(比如归为「节目开始前」)。
步骤3:统计每个节目的观看人数
最后按节目分组统计日志数量,就是对应的观看人数了:
# 按节目标题和开始时间分组,统计日志条目数 viewer_stats = matched_data.groupby(['title', 'startTime_dt'])['logid'].count().reset_index() # 重命名列名,让结果更清晰 viewer_stats.rename(columns={'logid': 'viewer_count'}, inplace=True) print(viewer_stats)
用你的示例数据运行的话,结果里第一个节目之前的两条日志会显示NaN,第三条0:01:20的日志会匹配到第一个节目"Amiről a kövek mesélnek",所以这个节目的viewer_count会是1。
可选:处理节目开始前的条目
如果想把节目开始前的条目单独统计,可以补充这段代码:
# 给NaN的标题赋值为「节目开始前」 matched_data['title'] = matched_data['title'].fillna('节目开始前') # 给对应时间赋值为当天0点 matched_data['startTime_dt'] = matched_data['startTime_dt'].fillna(pd.to_datetime('2019-05-29 00:00:00')) # 重新统计 viewer_stats = matched_data.groupby(['title', 'startTime_dt'])['logid'].count().reset_index()
这样就能完整统计所有日志的归属啦!
内容的提问来源于stack exchange,提问作者midi
相关产品推荐
相关产品推荐

