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

Pandas计算工作日时处理空结束日期的报错解决咨询

Pandas计算工作日时处理空结束日期的报错解决咨询

看起来你已经搞定了从固定列宽txt文件读取数据、正常场景下计算工作日的逻辑,但卡在了空结束日期导致的NaT报错上——这个问题我之前处理老系统导出的数据时也碰到过,老数据库的空值经常给日期转换添乱,咱们一步步来解决:

问题根源

你当前的get_Cmplt_Date函数遇到空值时返回空字符串,后续转日期时会变成NaT(Not a Time),而pd.bdate_range完全不接受NaT作为起始/结束参数,所以触发了ValueError。

解决方案分两步:修正空值处理 + 安全计算工作日

1. 简化日期转换,让空值正确转为NaT

首先可以去掉冗余的conv_str和get_Cmplt_Date函数,直接用pd.to_datetime的errors='coerce'参数,自动把空值/无效值转为NaT:

from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
import pandas as pd
import numpy as np

def getCompDataFromFile():
    colspecsvalues = (
        (0, 9),
        (10, 34),
        (35, 45),
        (46, 56)
    )
    col_names = ["EmpID", "Name", "StartDt", "CompleteDt"]
    
    # 直接读入,不需要额外的字符串转换
    df = pd.read_fwf(r'path to file', colspecs=colspecsvalues, names=col_names)
    
    # 转日期,空值自动转为NaT
    df['StartDt'] = pd.to_datetime(df['StartDt'], format='%m/%d/%Y', errors='coerce')
    df['CompleteDt'] = pd.to_datetime(df['CompleteDt'], format='%m/%d/%Y', errors='coerce')
    
    # 定义美国工作日日历
    us_bus = CustomBusinessDay(calendar=USFederalHolidayCalendar())
    
    # 定义安全计算工作日的函数
    def calculate_work_days(row):
        start = row['StartDt']
        end = row['CompleteDt']
        # 检查结束日期是否为空
        if pd.isna(end):
            # 这里可以按需修改:比如返回NaN表示未完成,或者计算到当前日期
            # 示例1:返回NaN
            return pd.NA
            # 示例2:计算到今天的工作日数
            # end = pd.Timestamp.today().normalize()
            # return len(pd.bdate_range(start, end, freq=us_bus)) - 1
        # 正常计算工作日(减1是因为bdate_range包含首尾两天)
        return len(pd.bdate_range(start, end, freq=us_bus)) - 1
    
    # 应用函数生成新列
    df['DaysToCmplt'] = df.apply(calculate_work_days, axis=1)
    return df

# 执行函数
DaysToCmplt = getCompDataFromFile()
print(DaysToCmplt)

2. 可选:用矢量化操作替代apply提升效率

如果你的数据量很大,apply会比较慢,可以用np.where结合busday_count来实现矢量化计算:

# 替代apply的矢量化写法
holidays = us_bus.holidays(start=df['StartDt'].min(), end=df['CompleteDt'].max()).date
df['DaysToCmplt'] = np.where(
    df['CompleteDt'].notna(),
    np.busday_count(df['StartDt'].dt.date, df['CompleteDt'].dt.date, holidays=holidays),
    pd.NA  # 空结束日期的处理逻辑
)

这个写法比apply快很多,适合大数据集。

额外提示

  • 如果你希望空结束日期显示为“未完成”而不是NaN,可以把返回值改成字符串:return "未完成"
  • 注意pd.Timestamp.today()会包含当前时间,用normalize()可以转成当天的0点,避免时间部分影响计算

备注:内容来源于stack exchange,提问作者RhettBrindle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 09:12:49