Snowpark 中填充 Decimal 类型列缺失值的正确方法

在 snowpark 中使用 `na.fill()` 填充缺失值时,若目标列为 `decimaltype`(如 `decimaltype(38, 12)`),直接传入 `int` 或 `float`(如 `0` 或 `0.0`)会因类型不匹配而跳过填充;必须显式提供 `decimal.decimal` 实例才能成功。

Snowpark 对数据类型匹配要求严格:DecimalType 列仅接受 Python 的 decimal.Decimal 对象,不兼容内置 int 或 float。这是由 Snowflake 底层对高精度数值的强类型约束决定的——int(0) 和 float(0.0) 在语义和精度上均无法无损映射到 DECIMAL(38,12),因此 df.na.fill(0) 或 df.na.fill(0.0) 会静默跳过该列,并输出警告日志:“Input value type doesn't match the target column data type”。

✅ 正确做法是:为每个 DecimalType 列单独指定 decimal.Decimal 值,通过字典形式传入 na.fill():

from decimal import Decimal

# 假设 DataFrame 包含列 'MEDIAN_AQI'(DecimalType(38, 12))和其他列
df = df.na.fill({
    "MEDIAN_AQI": Decimal('0'),        # ✅ 精确零,推荐用字符串构造避免浮点误差
    "OTHER_INT_COL": 0,                # ✅ int 可用于 IntegerType/LongType
    "FLOAT_COL": 0.0                   # ✅ float 可用于 FloatType/DoubleType
})
? 提示:使用 Decimal('0')(字符串构造)比 Decimal(0) 更安全,可完全规避浮点字面量隐式转换带来的精度风险。

⚠️ 注意事项:

  • 不支持全局 na.fill(0) 对混合类型 DataFrame 的“一键填充”,必须按列指定适配类型;

  • 若需批量处理多个 Decimal 列,可先获取 schema,筛选 DecimalType 字段,再动态构建填充字典:

    from snowflake.snowpark.types import DecimalType
    from decimal import Decimal
    
    decimal_cols = [
        field.name for field in df.schema.fields 
        if isinstance(field.datatype, DecimalType)
    ]
    fill_dict = {col: Deci

    mal('0') for col in decimal_cols} df = df.na.fill(fill_dict)

? 替代方案(适用场景有限):
若业务允许降低精度要求,可将 DecimalType 列显式转为 DoubleType(支持 float 填充):

from snowflake.snowpark.types import DoubleType
df = df.with_column("MEDIAN_AQI", df["MEDIAN_AQI"].cast(DoubleType()))
df = df.na.fill({"MEDIAN_AQI": 0.0})  # ✅ now works

但此操作会丢失 DECIMAL 的精确小数位能力,仅建议用于分析型非金融场景

总之,尊重 Snowpark 的类型契约是关键:DecimalType → decimal.Decimal,FloatType → float,IntegerType → int。精准匹配,方能可靠填充。