如何解决Prophet库get_holidays_for_countries_and_years_list方法返回空列表的问题?

问题现象描述

在使用Facebook Prophet进行时间序列预测时,许多开发者会遇到get_holidays_for_countries_and_years_list方法返回空列表的异常情况。这个方法本应返回指定国家和年份的节假日数据,但实际运行时却得到[]。这种现象通常发生在以下场景:

  • 跨国家/地区的多区域分析时
  • 处理非标准年份范围时
  • 使用自定义节假日配置时

根本原因分析

经过对Prophet源码的深入剖析,我们发现这个问题主要源于三个层面的原因:

1. 国家代码规范问题

Prophet内部使用ISO 3166-1标准的2字母国家代码,但很多开发者会错误地使用:

  1. 3字母代码(如USA代替US)
  2. 非标准缩写(如UK代替GB)
  3. 包含空格或特殊字符的字符串
# 错误示例
prophet.get_holidays_for_countries_and_years_list(['USA'], [2023])

# 正确写法
prophet.get_holidays_for_countries_and_years_list(['US'], [2023])

2. 年份范围限制

Prophet的节假日数据集存在以下限制:

国家有效年份范围
中国(CN)1995-2049
美国(US)2008-2030
德国(DE)2016-2030

当请求超出这些范围的年份时,方法会静默返回空列表。

3. 数据加载机制缺陷

Prophet通过pandas读取内置的holidays.csv文件,该文件:

  • 存储路径:prophet/static_data/holidays.csv
  • 包含约200个国家的节假日数据
  • 使用内存缓存机制

在以下情况会导致数据加载失败:

  1. 文件权限问题
  2. 虚拟环境路径解析错误
  3. 缓存未正确更新

解决方案

方案1:验证国家代码

使用pycountry库进行代码转换:

import pycountry

def validate_country_code(country_input):
    try:
        country = pycountry.countries.lookup(country_input)
        return country.alpha_2
    except LookupError:
        raise ValueError(f"Invalid country code: {country_input}")

方案2:扩展节假日数据

创建自定义节假日DataFrame:

custom_holidays = pd.DataFrame({
    'ds': pd.to_datetime(['2023-01-01', '2023-12-25']),
    'holiday': ['New Year', 'Christmas'],
    'lower_window': 0,
    'upper_window': 1,
    'country': 'US'
})

model.add_country_holidays(country_name='US', holidays=custom_holidays)

方案3:调试源码

修改Prophet的holidays.py源码:

# 定位到get_holiday_names方法
def get_holiday_names(country, year):
    if country not in self.country_holidays:
        print(f"Debug: Country {country} not found")  # 添加调试信息
        return []
    # ...原有代码...

最佳实践建议

基于实际项目经验,我们推荐:

  1. 始终检查返回值的长度
  2. 使用try-except捕获潜在异常
  3. 维护自定义节假日数据库
  4. 定期更新Prophet版本

性能优化技巧

处理大规模节假日数据时:

  • 使用functools.lru_cache缓存查询结果
  • 预加载常用国家的节假日数据
  • 采用多线程批量查询