Spark读取高标度零值decimal转科学计数法,如何按原格式写入CSV?
解决方案
针对Spark 2.4.8中Decimal类型零值写入CSV时自动转为科学计数法的问题,可通过动态识别Schema并格式化Decimal字段的方式解决,完全适配通用型应用场景:
核心思路
- 自动遍历输入DataFrame的Schema,识别所有
DecimalType字段及其对应的标度(scale) - 对每个Decimal字段,根据其scale值格式化为固定小数位数的字符串,同时去除千分位分隔符
- 将格式化后的DataFrame写入CSV,此时字符串类型的数值不会触发科学计数法转换
代码实现(Scala)
import org.apache.spark.sql.types.DecimalType import org.apache.spark.sql.functions._ // 1. 提取所有Decimal类型字段的名称与对应scale val decimalFieldInfo = df.schema.fields .filter(_.dataType.isInstanceOf[DecimalType]) .map(field => { val decimalType = field.dataType.asInstanceOf[DecimalType] (field.name, decimalType.scale) }) // 2. 批量格式化Decimal字段:转为指定小数位的字符串,移除千分位逗号 val formattedDataFrame = decimalFieldInfo.foldLeft(df) { (currentDf, fieldMeta) => val (colName, scale) = fieldMeta currentDf.withColumn( colName, regexp_replace(format_number(col(colName), scale), ",", "") ) } // 3. 写入CSV文件 formattedDataFrame.write .option("header", "true") // 根据需求开启表头 .mode("overwrite") // 根据需求设置写入模式 .csv("/your/output/path")
关键细节说明
format_number(col, scale):将Decimal数值格式化为保留scale位小数的字符串,例如0.00000000(scale=8)会被格式化为"0.00000000",但默认会为大数添加千分位逗号regexp_replace(..., ",", ""):移除千分位逗号,避免数值格式异常- 动态遍历Schema:无需提前知晓表结构或字段类型,自动适配所有Decimal字段的不同precision和scale
- 空值处理:若Decimal字段为null,格式化后仍为null,不影响CSV写入结果
内容的提问来源于stack exchange,提问作者bp2010
相关产品推荐
相关产品推荐

