如何在Pandas使用read_parquet读取Parquet文件时保留数据类型?
如何在读取Parquet文件时保留嵌套字典的原始数据类型?
你遇到的问题是因为Parquet是强类型存储格式,当pandas的object列中混合了int和np.nan(属于float类型)时,写入Parquet时会被自动推断为float64类型,导致读取后整数变为浮点数,np.nan变为None。以下是几种可行的解决方案:
方案1:使用Pandas可空整数类型替代原生int和np.nan
将原始数据中的int转换为Pandas的Int64可空整数类型,并用pd.NA替代np.nan,这样写入Parquet时能保留整数类型的缺失值:
import pandas as pd import numpy as np # 构造使用可空整数类型的DataFrame df = pd.DataFrame({ "a": [ [{"b": pd.Int64Dtype.type(1)}], [{"b": pd.NA}] ] }) # 写入Parquet文件 df.to_parquet("a.parquet", engine="pyarrow") # 读取文件 df_read = pd.read_parquet("a.parquet") print(df_read) # 输出: # a # 0 [{'b': 1}] # 1 [{'b': <NA>}] # 验证类型 print(type(df_read.iloc[0, 0][0]['b'])) # <class 'int'> print(type(df_read.iloc[1, 0][0]['b'])) # <class 'pandas._libs.missing.NAType'>
方案2:写入时指定PyArrow Schema强制类型
通过定义PyArrow的Schema,明确嵌套字段的类型为允许null的整数,强制Parquet存储时使用指定类型:
import pandas as pd import numpy as np import pyarrow as pa import pyarrow.parquet as pq # 原始DataFrame df = pd.DataFrame({"a": [[{"b": 1}], [{"b": np.nan}]]}) # 定义Schema:a为列表类型,元素是结构体,b字段为允许null的int64 schema = pa.schema([ pa.field("a", pa.list_(pa.struct([pa.field("b", pa.int64())]))) ]) # 转换为PyArrow Table并指定Schema table = pa.Table.from_pandas(df, schema=schema) # 写入Parquet文件 pq.write_table(table, "a.parquet") # 读取文件 df_read = pd.read_parquet("a.parquet") print(df_read) # 输出: # a # 0 [{'b': 1}] # 1 [{'b': <NA>}]
方案3:读取后手动转换类型(仅适合小数据集)
如果无法修改写入逻辑,可以在读取后遍历数据,将符合整数条件的浮点数转回int,None转回np.nan:
import pandas as pd import numpy as np df_read = pd.read_parquet("a.parquet") def convert_nested_types(lst): for d in lst: for k, v in d.items(): if v is not None and isinstance(v, float) and v.is_integer(): d[k] = int(v) elif v is None: d[k] = np.nan return lst df_read['a'] = df_read['a'].apply(convert_nested_types) print(df_read) # 输出: # a # 0 [{'b': 1}] # 1 [{'b': nan}]
核心原因说明
Parquet是强类型列式存储格式,PyArrow(Pandas默认的Parquet引擎)在处理object列中的混合类型时,会自动选择能覆盖所有值的最宽泛类型(比如int和np.nan会被推断为float64)。要保留原始类型,必须明确指定支持null的整数类型,避免类型自动提升。
内容的提问来源于stack exchange,提问作者user3595632
相关产品推荐
相关产品推荐

