使用holiday包生成指定假期时触发NumPy ValueError问题求助
动态生成指定假期列表对应日期并计算工作日
问题背景
已有如下DataFrame:
PredictionTargetDateEOM PredictionTargetDateBOM DayAfterTargetDateEOM business_days 0 2018-12-31 2018-12-01 2019-01-01 20 1 2019-01-31 2019-01-01 2019-02-01 21 2 2019-02-28 2019-02-01 2019-03-01 20 3 2018-11-30 2018-11-01 2018-12-01 21 4 2018-10-31 2018-10-01 2018-11-01 23 ... ... ... ... ... 172422 2020-10-31 2020-10-01 2020-11-01 22 172423 2020-11-30 2020-11-01 2020-12-01 20 172424 2020-12-31 2020-12-01 2021-01-01 22 172425 2020-09-30 2020-09-01 2020-10-01 21 172426 2020-08-31 2020-08-01 2020-09-01 21
原本使用holiday包计算工作日的代码:
predicted_df['PredictionTargetDateBOM'] = predicted_df.apply(lambda x: pd.to_datetime(x['PredictionTargetDateEOM']).replace(day=1), axis = 1) #Get first day of the target month predicted_df['PredictionTargetDateEOM'] = pd.to_datetime(predicted_df['PredictionTargetDateEOM']) predicted_df['DayAfterTargetDateEOM'] = predicted_df['PredictionTargetDateEOM'] + timedelta(days=1) #Get the first day of the month after target month. i.e. M+2 predicted_df['business_days_bankers'] = predicted_df.apply(lambda x: np.busday_count(x['PredictionTargetDateBOM'].date(), x['DayAfterTargetDateEOM'].date(), holidays=[list(holidays.US(years=x['PredictionTargetDateBOM'].year).keys())[index] for index in [list(holidays.US(years=x['PredictionTargetDateBOM'].year).values()).index(item) for item in rocket_holiday_including_observed if item in list(holidays.US(years=x['PredictionTargetDateBOM'].year).values())]] ), axis = 1) #Count number of business days of the target month
现在希望改用自定义假期列表rocket_holiday:
["New Year's Day", 'Martin Luther King Jr. Day', 'Memorial Day', 'Independence Day', 'Labor Day', 'Thanksgiving', 'Christmas Day', "New Year's Day (Observed)", 'Martin Luther King Jr. Day (Observed)', 'Memorial Day (Observed)', 'Independence Day (Observed)', 'Labor Day (Observed)', 'Thanksgiving (Observed)', 'Christmas Day (Observed)']
直接添加代码后触发错误:ValueError: Cannot create a NumPy datetime other than NaT with generic units,需要根据年份动态生成该列表对应的假期日期,而非硬编码。
解决方案
核心思路是针对每行数据的年份,从holidays.US中筛选出rocket_holiday列表里对应的假期日期,再传入np.busday_count。
步骤1:定义筛选假期日期的辅助函数
import holidays import numpy as np import pandas as pd from datetime import timedelta def get_rocket_holidays(year, rocket_holiday_list): # 获取该年份的所有美国假期(含调休) us_holidays = holidays.US(years=year) # 筛选出名称在目标列表中的假期,提取日期 rocket_dates = [date for date, name in us_holidays.items() if name in rocket_holiday_list] # 转换为numpy可识别的datetime64格式 return np.array(rocket_dates, dtype='datetime64[D]')
步骤2:应用函数计算工作日
# 定义你的rocket_holiday列表 rocket_holiday = [ "New Year's Day", 'Martin Luther King Jr. Day', 'Memorial Day', 'Independence Day', 'Labor Day', 'Thanksgiving', 'Christmas Day', "New Year's Day (Observed)", 'Martin Luther King Jr. Day (Observed)', 'Memorial Day (Observed)', 'Independence Day (Observed)', 'Labor Day (Observed)', 'Thanksgiving (Observed)', 'Christmas Day (Observed)' ] # 计算rocket规则下的工作日数 predicted_df['business_days_rocket'] = predicted_df.apply( lambda x: np.busday_count( x['PredictionTargetDateBOM'].date(), x['DayAfterTargetDateEOM'].date(), holidays=get_rocket_holidays(x['PredictionTargetDateBOM'].year, rocket_holiday) ), axis=1 )
错误原因说明
之前的错误是因为直接把假期名称字符串列表传给了np.busday_count的holidays参数,但该参数要求传入日期对象/数组,而非名称。通过辅助函数按年份动态提取对应假期的日期,就能解决类型不匹配的问题。
内容的提问来源于stack exchange,提问作者Hefe
相关产品推荐
相关产品推荐

