使用pd.read_parquet加载Parquet文件时遇ValueError: year 0 is out of range
解决Parquet加载时"year 0 is out of range"的错误
问题根源:Parquet文件中包含年份为0的日期/时间戳值,但pandas的datetime类型不支持公历中不存在的year 0,导致pyarrow在将Arrow表转换为pandas DataFrame时抛出错误。
解决方案
1. 先定位问题列
先通过pyarrow读取Parquet文件(不会触发转换错误),找出包含year 0的日期列:
import pyarrow.parquet as pq import pyarrow as pa # 读取为Arrow Table table = pq.read_table('G34I9.snappy.parquet') # 遍历检查所有日期/时间戳列 for col_name in table.column_names: col = table[col_name] col_type = col.type # 匹配所有日期和时间戳类型 if (pa.types.is_date(col_type) or pa.types.is_timestamp(col_type)): min_val = col.min() if min_val is not None and min_val.year == 0: print(f"存在问题的列: {col_name}")
2. 将问题列读取为字符串
直接指定问题列以字符串类型加载,避开datetime转换错误,后续可按需清洗:
import pandas as pd # 单个问题列指定类型 df = pd.read_parquet('G34I9.snappy.parquet', dtype={'问题列名': str}) # 批量处理所有日期列(不确定具体列时) date_cols = [col for col in table.column_names if (pa.types.is_date(table[col].type) or pa.types.is_timestamp(table[col].type))] dtype_map = {col: str for col in date_cols} df = pd.read_parquet('G34I9.snappy.parquet', dtype=dtype_map)
3. 先清洗数据再转换为DataFrame
用pyarrow的计算功能先过滤或替换year 0的日期值,再转为pandas DataFrame:
import pyarrow.compute as pc table = pq.read_table('G34I9.snappy.parquet') for col_name in table.column_names: col = table[col_name] col_type = col.type if (pa.types.is_date(col_type) or pa.types.is_timestamp(col_type)): # 筛选出year=0的记录,替换为None(转pandas后变为NaT) mask = pc.year(col) == 0 cleaned_col = pc.if_else(mask, None, col) # 替换原列 table = table.set_column(table.column_names.index(col_name), col_name, cleaned_col) # 转换为pandas DataFrame df = table.to_pandas()
4. 修改转换选项(应急方案)
通过设置Arrow转pandas的选项,跳过datetime转换限制,但可能导致数据类型变化:
df = table.to_pandas(convert_options=pa.ArrowPandasConvertOptions( timestamp_as_object=True # 将时间戳转为object类型,避免转换报错 ))
内容的提问来源于stack exchange,提问作者gervazy
相关产品推荐
相关产品推荐

