如何在Pandas中计算含NaT的日期列工作日差值并生成新列
计算Pandas DataFrame中日期列的工作日差值(处理NaT值)
先快速梳理两种场景的基础实现:
- 无需排除周末:直接让两列日期相减就行,代码超简单:
df['Difference in Days'] = df['Column 2'] - df['Column 1'] # 如果需要把Timedelta类型转成纯天数数值,加.dt.days # df['Difference in Days'] = (df['Column 2'] - df['Column 1']).dt.days
接下来重点解决你提到的排除周末+处理NaT值的需求,分两步走:
1. 先把日期列转成标准datetime类型
np.busday_count()只认datetime64类型,所以先给原始日期列做格式转换:
import pandas as pd # 根据你的日期格式(日/月/两位年)指定format,格式不同的话记得调整 df['Column 1'] = pd.to_datetime(df['Column 1'], format='%d/%m/%y') df['Column 2'] = pd.to_datetime(df['Column 2'], format='%d/%m/%y')
2. 计算工作日差值并处理NaT
这里有两种实现方式,按需选:
方式一:向量化操作(高效,适合大数据量)
用np.where结合掩码判断,先筛选出两列都不为NaT的行,再计算工作日差,其他行返回空值:
import numpy as np # 创建掩码:标记两列都不为空的行 valid_dates_mask = pd.notna(df['Column 1']) & pd.notna(df['Column 2']) # 计算差值:符合条件的用busday_count,否则返回pd.NA(对应你要的Blank) df['Difference in Days'] = np.where( valid_dates_mask, np.busday_count(df['Column 1'].to_numpy(), df['Column 2'].to_numpy()), pd.NA )
方式二:逐行处理(直观,适合新手理解)
写个自定义函数,用apply逐行检查并计算:
def get_business_days(row): # 只要任一列为NaT,就返回空值 if pd.isna(row['Column 1']) or pd.isna(row['Column 2']): return pd.NA # 转成numpy datetime64类型后计算工作日差 start_date = row['Column 1'].to_numpy() end_date = row['Column 2'].to_numpy() return np.busday_count(start_date, end_date) df['Difference in Days'] = df.apply(get_business_days, axis=1)
验证示例结果
用你给出的初始DataFrame测试:
初始数据
| Column 1 | Column 2 |
|---|---|
| 07/10/20 | 09/10/20 |
| 07/10/20 | 12/10/20 |
| NaT | 09/10/20 |
| 07/10/20 | NaT |
运行代码后结果
| Column 1 | Column 2 | Difference in Days |
|---|---|---|
| 2020-10-07 | 2020-10-09 | 2 |
| 2020-10-07 | 2020-10-12 | 3 |
| NaT | 2020-10-09 | |
| 2020-10-07 | NaT |
如果希望把<NA>显示为空白字符串,可以加一句:
df['Difference in Days'] = df['Difference in Days'].fillna('')
额外提一句:如果需要排除节假日,可以给np.busday_count()加holidays参数,传入一个格式统一为datetime64的节假日日期数组即可。
内容的提问来源于stack exchange,提问作者Josh Fox
相关产品推荐
相关产品推荐

