为何DuckDB导入Polars的Enum列会转换为VARCHAR列?
为什么DuckDB不会将Polars的Enum类型转换为自身的Enum类型?
问题重现
用户使用Polars创建包含Enum列的DataFrame:
import polars as pl values = ["a", "b", "c"] df = pl.DataFrame(pl.Series("x", values, dtype=pl.Enum(values))) print(df)
执行结果:
shape: (3, 1) ┌──────┐ │ x │ │ --- │ │ enum │ ╞══════╡ │ a │ │ b │ │ c │ └──────┘
随后用DuckDB查询该DataFrame:
import duckdb as ddb ddb.sql("SELECT * FROM df").show()
查询结果显示原Enum列被转换为VARCHAR类型:
┌─────────┐ │ x │ │ varchar │ ├─────────┤ │ a │ │ b │ │ c │ └─────────┘
用户最初怀疑是Parquet文件读取导致的问题,但直接查询Polars DataFrame也出现同样情况,因此提出疑问:为什么DuckDB不将Polars的Enum转换为DuckDB的Enum类型?
原因解释
核心原因是Polars与DuckDB的Enum类型在底层实现、类型映射逻辑上存在差异,且当前DuckDB的Python集成未针对Polars Enum做专门的转换适配:
- Polars的Enum基于字符串集合定义,内部可能用整数编码存储,但对外以字符串形式暴露;
- DuckDB的Enum类型需要显式定义枚举值集合,而DuckDB读取Polars DataFrame时,默认仅识别通用基础类型(如字符串、数值),不会主动解析Polars Enum的元数据来创建对应的DuckDB Enum类型;
- 无论直接读取Polars DataFrame还是读取Parquet文件,本质都是DuckDB没有内置Polars Enum到自身Enum的转换逻辑,因此会降级处理为VARCHAR类型。
如果需要在DuckDB中保留Enum类型,可以手动显式转换:先在DuckDB中定义对应Enum类型,再将Polars的Enum列转换为该类型,示例代码如下:
import duckdb as ddb import polars as pl values = ["a", "b", "c"] df = pl.DataFrame(pl.Series("x", values, dtype=pl.Enum(values))) # 在DuckDB中定义枚举类型 ddb.sql(f"CREATE TYPE my_enum AS ENUM({', '.join([f'{repr(v)}' for v in values])})") # 转换列类型并查询 ddb.sql("SELECT CAST(x AS my_enum) FROM df").show()
内容的提问来源于stack exchange,提问作者bzm3r
相关产品推荐
相关产品推荐

