scala - BigDecimal setScale 在 Spark UDF 中不起作用
问题描述
我试图将 json 列转换为映射。我尝试使用 udf 将 json 转换为 map。但它没有按预期工作。
val df1 = Seq(("{\"k\":10.004}")).toDF("json")
def udfJsonStrToMapDecimal = udf((jsonStr: String)=> { var jsonMap:Map[String,Any] = parse(jsonStr).values.asInstanceOf[Map[String, Any]]
jsonMap.map{case(k,v) => (k,BigDecimal.decimal(v.asInstanceOf[Double]).setScale(6))}.toMap
})
val f = df1.withColumn("map",udfJsonStrToMapDecimal($"json"))
scala> f.printSchema
root
|-- json: string (nullable = true)
|-- map: map (nullable = true)
| |-- key: string
| |-- value: decimal(38,18) (valueContainsNull = true)
而不是十进制(38,6)它将值转换为十进制(38,18) 这里需要帮助
解决方案
默认的十进制精度是DecimalType(38, 18)
,我不确定您要做什么,但是
您可以将当前的十进制类型转换为
df1.withColumn("map",udfJsonStrToMapDecimal($"json").cast("map<string, decimal(38,6)>"))
架构:
root
|-- json: string (nullable = true)
|-- map: map (nullable = true)
| |-- key: string
| |-- value: decimal(38,6) (valueContainsNull = true)
或者您也可以定义模式并直接读取为 JSON
val schema = StructType(StructField("k", DecimalType(38, 6), nullable = false) :: Nil)
val df1 = Seq(("{\"k\":10.004}")).toDF("json")
val result = df1.withColumn("value", from_json($"json", schema))
架构:
root
|-- json: string (nullable = true)
|-- value: struct (nullable = true)
| |-- k: decimal(38,6) (nullable = true)
推荐阅读
- java - 在流中找到满足该元素的条件的第一个元素
- acumos - Error executing cmn-data-svc-ddl-dml-mysql-2.2-sql during AIO
- ios - Auto-generated Core Data accessor returns deleted objects
- php - Pagesource shows only html tags using phantomjs
- task - 如何在 CCS (Code Composer Studio) 9 上跟踪和分析 FreeRTOS 任务
- c# - 如何从 Configuration Builder 中的 Key Vault 获取密钥的值
- python - Build DataFrame from list of
- node.js - JOI - 通过 requiredKeys 强制要求
- c - 在 C 中读取 /proc/cpuinfo 并打印匹配行
- r - 我可以在 R 软件中将我所有的日期都放在一个变量中吗?