You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DataFrame连接后小数精度丢失,如何保留原始数值?

解决CSV导入后Join丢失小数精度问题

问题说明

  • 将CSV文件导入为DataFrame后,能看到0.000001这类高精度小数
  • 连接多个DataFrame后,数值末尾的1丢失
  • 并非显示问题:执行(x/sum(x)).overWindow(partitionBy())时返回null

解决步骤

1. 导入CSV时强制指定高精度数据类型

CSV默认会将小数解析为Double类型,而Double的精度有限,无法保留极小值的末尾有效数字。改用Decimal类型可以解决这个问题(精度和刻度可根据实际数据调整)。以Spark为例:

import org.apache.spark.sql.types.{StructType, StructField, DecimalType, StringType}

// 自定义Schema,给目标列指定Decimal类型
val csvSchema = StructType(Seq(
  StructField("value_col", DecimalType(38, 10), nullable = true),
  StructField("join_col", StringType, nullable = true)
))

// 导入CSV时应用自定义Schema
val sourceDf = spark.read
  .option("header", "true")
  .schema(csvSchema)
  .csv("path/to/your/file.csv")

2. 确保Join操作的列类型一致

如果用于Join的列是数值型,要保证所有参与Join的DataFrame中该列的类型统一为Decimal,避免隐式类型转换导致精度丢失。

3. 显式保留Join后的列类型

部分Join操作可能会自动转换列类型,可在Join后显式转换目标列到Decimal类型:

import org.apache.spark.sql.functions.col

val joinedDf = df1.join(df2, Seq("join_col"))
  .withColumn("value_col", col("value_col").cast(DecimalType(38, 10)))

4. 用高精度类型执行窗口计算

使用Decimal类型计算时,sum(x)会保留极小值的精度,避免因sum结果为0导致除以0返回null:

import org.apache.spark.sql.expressions.Window

val windowSpec = Window.partitionBy("group_col")
val resultDf = joinedDf.withColumn(
  "ratio",
  col("value_col").divide(sum(col("value_col")).over(windowSpec))
)

内容的提问来源于stack exchange,提问作者MagMru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:20:57