如何基于日期范围统计日粒度在场人数并绘制时序折线图
日粒度在场人数统计与可视化实现方案
核心判定规则:成员在指定日期在场的充要条件为 进入日期 ≤ 统计日期 ≤ 离开日期,所有逻辑都基于这个规则实现。
前置依赖与数据预处理
首先导入需要的库,统一将日期字段转为标准时间格式,避免字符串比对出错:
import pandas as pd import matplotlib.pyplot as plt from matplotlib.dates import DateFormatter # 替换为实际数据读取逻辑即可,示例为题目给出的样例数据 df = pd.DataFrame({ 'member_name': ['John', 'Adam', 'Tyler', 'Amy'], 'entry_date': ['2015-01-01', '2015-01-01', '2016-01-01', '2017-06-01'], 'exit_date': ['2020-01-01', '2019-01-01', '2017-01-01', '2020-01-01'] }) # 日期字段统一转datetime类型 df['entry_date'] = pd.to_datetime(df['entry_date']) df['exit_date'] = pd.to_datetime(df['exit_date'])
需求A:指定日期在场人数统计
直接通过布尔索引筛选符合条件的记录即可,单日期查询毫秒级返回:
def get_daily_count(target_date: str) -> int: target = pd.to_datetime(target_date) # 筛选进入时间不晚于目标日、离开时间不早于目标日的成员 return df[(df['entry_date'] <= target) & (df['exit_date'] >= target)].shape[0] # 样例测试:查询2016-06-01在场人数 print(get_daily_count('2016-06-01')) # 输出3,与预期结果一致
需求B:日粒度在场人数折线图绘制
不要使用逐日期循环统计的方法,数据量大时性能极差。采用事件流累计法,时间复杂度O(n),百万级数据也能秒级出结果:
- 将每条成员记录拆为两个事件:进入日人数+1,离开日次日人数-1(离开当日成员仍在场,所以次日才扣减人数)
- 按日期聚合每日人数变动值
- 生成覆盖全周期的连续日期序列,补全无人员进出的日期
- 对每日变动值做累计求和,得到每日在场总人数
- 基于结果绘制折线图
完整代码如下:
# 构造进出事件流 entry_records = pd.DataFrame({'date': df['entry_date'], 'delta': 1}) exit_records = pd.DataFrame({'date': df['exit_date'] + pd.Timedelta(days=1), 'delta': -1}) all_events = pd.concat([entry_records, exit_records]).sort_values('date') # 生成完整日序列,计算每日在场人数 full_dates = pd.date_range(start=all_events['date'].min(), end=df['exit_date'].max(), freq='D') daily_change = all_events.groupby('date')['delta'].sum().reindex(full_dates, fill_value=0) daily_count = daily_change.cumsum().reset_index(name='present_count').rename(columns={'index': 'date'}) # 绘制折线图 plt.figure(figsize=(12, 4)) plt.plot(daily_count['date'], daily_count['present_count'], linewidth=1.5, color='#1f77b4') # 坐标轴格式调整 plt.gca().xaxis.set_major_formatter(DateFormatter("%Y-%m")) plt.gcf().autofmt_xdate() plt.xlabel('日期') plt.ylabel('在场人数') plt.title('设施每日在场人数变化趋势') plt.grid(alpha=0.3) plt.tight_layout() plt.show()
性能说明:事件流累计法不需要对每个日期遍历全量成员数据,哪怕是跨度10年、十万级成员记录的场景,计算耗时也不会超过1秒,完全满足日粒度细统计的需求。
内容的提问来源于stack exchange,提问作者Jordin M
相关产品推荐
相关产品推荐

