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

如何高效计算DataFrame多日期列间的工作日天数(适配多列场景)

问题:高效计算DataFrame多日期列间的工作日天数

我有一个包含4列日期数据的DataFrame,具体数据如下:

col1       col2       col3       col4
0  2021-10-18  2021-10-27  2021-11-08  2021-11-21
1  2021-01-30  2021-02-01  2021-02-28  2021-03-18
2  2021-08-17  2021-08-20  2021-09-02  2021-09-07

我希望计算这些日期列之间的工作日天数,目前已实现的代码如下:

col1 = [d.date() for d in df['col1']]
col2 = [d.date() for d in df['col2 ']]
col3 = [d.date() for d in df['col3']]
col4 = [d.date() for d in df['col4 ']]
df['bday1'] = np.busday_count(col1, col2)
df['bday2'] = np.busday_count(col2, col3)
df['bday3'] = np.busday_count(col3, col4)

请问是否存在更高效的实现方式?尤其是当DataFrame包含更多日期列时,该如何优化这一计算过程?


优化方案

当然有更高效的方式!你的当前代码需要手动逐个处理列,当日期列数量增多时会非常繁琐,而且重复的列表推导也不够优雅。这里有几个实用的优化思路:

1. 先统一转换日期格式,省去重复类型转换

首先确保你的日期列已经是datetime64类型(如果还不是,先运行df = df.apply(pd.to_datetime))。numpy.busday_count其实可以直接接收pandas的Series(只要是datetime类型),完全不需要手动转成date()对象的列表,这一步能省去大量重复代码:

import numpy as np
import pandas as pd

# 确保日期列是datetime类型
df = df.apply(pd.to_datetime)

# 直接用Series计算,无需手动转列表
df['bday1'] = np.busday_count(df['col1'], df['col2'])
df['bday2'] = np.busday_count(df['col2'], df['col3'])
df['bday3'] = np.busday_count(df['col3'], df['col4'])

2. 用循环批量处理,适配任意数量的日期列

如果你的DataFrame有N个日期列(比如col1到coln),可以通过循环遍历相邻列对来自动生成工作日差列,完全不用手动写每一行:

# 获取所有日期列的名称(如果日期列不连续,可手动指定列名列表)
date_cols = df.columns.tolist()

# 遍历相邻的列对
for i in range(len(date_cols)-1):
    col_start = date_cols[i]
    col_end = date_cols[i+1]
    # 生成直观的新列名
    new_col_name = f'bday_{col_start}_to_{col_end}'
    df[new_col_name] = np.busday_count(df[col_start], df[col_end])

这样不管你有5列还是20列日期数据,都能一键生成所有相邻列的工作日差,代码复用性拉满。

3. 利用pandas的shift做向量化运算,适配超大数据集

如果你的数据集非常大,Python层面的循环可能会影响性能,这时可以用shift方法把日期列对齐,再做全量向量化计算:

# 生成"下一列"的日期数据(去掉第一列)
next_date_df = df.shift(axis=1).iloc[:, 1:]
# 全量计算工作日差
bday_diff_values = np.busday_count(df.values, next_date_df.values)
# 把结果转成DataFrame并合并到原df
bday_diff_df = pd.DataFrame(
    bday_diff_values,
    columns=[f'bday{i+1}' for i in range(len(df.columns)-1)]
)
df = pd.concat([df, bday_diff_df], axis=1)

这种方法完全依赖numpy的底层运算,避免了Python循环的开销,在处理百万级行数据时性能优势会很明显。

额外提示

  • 如果需要排除自定义节假日,可以给np.busday_count传入holidays参数,比如np.busday_count(start, end, holidays=custom_holidays),其中custom_holidays是一个datetime对象的数组。
  • 一定要确保所有日期列的类型是datetime64[ns],字符串类型直接传入会报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:57:42