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

如何高效统计多列各日期区间行数?求替代现有方法的优化方案

需求与优化方案

需求背景

用户持有一个Pandas DataFrame,列对应流程的各个阶段,每行记录该行数据进入对应阶段的日期。核心需求:

  • 统计每个阶段(列)中日期落在指定区间内的行数
  • 最终用于绘制漏斗图分析阶段流失情况,同时对比不同日期区间的漏斗差异

最初错误的尝试代码

用户最初的代码逻辑有误,会错误统计跨区间的行,代码如下:

start = pd.to_datetime('2023-1-1')
end = pd.to_datetime('2023-3-30')
df[(df[list_of_cols] >= start).any(axis=1)) & (df[list_of_columns] <= end).any(axis=1))]
df[list_of_cols].count()

现有可行但繁琐的实现

用户编写了funnel_by_time函数可实现需求,但嵌套循环逻辑较繁琐,代码如下:

def funnel_by_time(df: pd.DataFrame, dates: list):
    df_dict = {date.strftime('%m/%d/%Y'): [] for date in dates[:-1]}
    # 为每个时间段创建统计列表
    for i in range(len(dates)-1):
        date_range = pd.date_range(dates[i], dates[i+1])
        
        # 统计每个阶段在当前日期区间内的行数
        for col in stage_cols:
            df_dict[dates[i].strftime('%m/%d/%Y')].append(
                df[col].isin(date_range).sum())
    return pd.DataFrame.from_dict(df_dict,
                                  orient='index',
                                  columns=stage_cols)

更简洁高效的优化方案

利用Pandas的向量化操作替代嵌套循环,既能提升运行效率,又能简化代码逻辑:

方案1:基于cut的分组统计

def funnel_by_time_optimized(df: pd.DataFrame, dates: list):
    # 将日期区间映射为起始日期标签
    time_labels = [d.strftime('%m/%d/%Y') for d in dates[:-1]]
    # 对所有阶段的日期做区间划分
    time_bins = pd.cut(df[stage_cols].stack(), bins=dates, labels=time_labels, include_lowest=True)
    
    # 分组统计各时间段、各阶段的有效行数
    result = (df[stage_cols]
              .stack()
              .reset_index(name='date')
              .assign(time_period=time_bins)
              .dropna(subset=['date'])
              .groupby(['time_period', 'level_1'])['date']
              .count()
              .unstack()
              .fillna(0)
              .astype(int))
    return result

方案2:向量化区间判断

如果不想使用cut,可以直接对每个区间做向量化的日期判断:

def funnel_by_time_vectorized(df: pd.DataFrame, dates: list):
    result = pd.DataFrame()
    for start, end in zip(dates[:-1], dates[1:]):
        # 对每个阶段列,统计日期在[start, end]范围内的行数
        counts = df[stage_cols].apply(lambda col: col.between(start, end).sum())
        result.loc[start.strftime('%m/%d/%Y'), :] = counts
    return result.astype(int)

方案优势

  • 依赖Pandas原生向量化操作,避免嵌套循环,数据量越大效率提升越明显
  • 代码逻辑更直观,可读性更强
  • 自动处理缺失日期的情况,无需额外判断逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:12:46