我的要求是将DataFrame中的所有Decimal数据类型转换为String。逻辑工作正常,类型简单但不适用于ArrayType。 这是逻辑: -
var df = spark.sql("select * from test_1")
for(dt <- df.dtypes) {
if(dt._2.substring(0,7) == "Decimal"){
df = df.withColumn(dt._1,df(dt._1).cast("String"))
}
}
但arrayType中的列保持不变,但它们是十进制类型。请帮助,我如何循环嵌套元素并将其转换为字符串。 这是我的数据帧的架构:
阶&GT; df.schema res77:org.apache.spark.sql.types.StructType = StructType(StructField(mstr_prov_id,StringType,真) StructField(prov_ctgry_cd,StringType,真) StructField(prov_orgnl_efctv_dt,TimestampType,真) StructField(prov_trmntn_dt,TimestampType,真) StructField(prov_trmntn_rsn_cd,StringType,真) StructField(npi_rqrd_ind,StringType,真) StructField(prov_stts_aray_txt,数组类型(StructType(StructField(PROV_STTS_KEY,DecimalType(22,0),真) StructField(PROV_STTS_EFCTV_DT,TimestampType,真) StructField(PROV_STTS_CD,StringType,真) StructField(PROV_STTS_TRMNTN_DT,TimestampType,真) StructField(PROV_STTS_TRMNTN_RSN_CD,StringType,TRUE)),真),真))
答案 0 :(得分:0)
您还可以投射复杂类型,例如如果你有像这个架构的数据框:
root
|-- arr: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- i: decimal(22,0) (nullable = true)
| | |-- j: double (nullable = false)
您可以通过执行以下操作来强制转换所有十进制类型的数组元素(在此示例中为字段i
):
df
.select($"arr".cast("array<struct<i:string,j:double>>"))
.printSchema()
root
|-- arr: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- i: string (nullable = true)
| | |-- j: double (nullable = true)
编辑:
如果您事先不知道架构,则可以使用decimal
替换原始架构中的string
:
val arraySchema = df.schema.fields(0).dataType.simpleString
val castedSchema = arraySchema.replaceAll("decimal\\(.*\\)","string")
df
.select($"arr".cast(castedSchema))
.show()
答案 1 :(得分:0)
如果您使用的是Spark 2.1及以上版本,那么以下投射应该适合您
val newSchema = DataType.fromJson(df.schema.json.replaceAll("(decimal\\(\\d+,\\d+\\))", "string")).asInstanceOf[StructType]
df.select(newSchema.map(field => col(field.name).cast(field.dataType)): _*)
应将所有小数类型转换为字符串类型。
但是如果你使用的spark版本低于上面提到的版本,并且因为结构列中有 timestamp 数据类型,你会遇到
TimestampType (of class org.apache.spark.sql.types.TimestampType$) scala.MatchError: TimestampType (of class org.apache.spark.sql.types.TimestampType$)
它是casting structs fails on Timestamp fields并已解决cast struct with timestamp field fails
答案 2 :(得分:0)
尝试一下(您与==的比较可能不是您想要的)
var df = spark.sql("select * from test_1")
for(dt <- df.dtypes) {
if("Decimal".equalsIgnoreCase(dt._2.substring(0,Math.min(7, dt._2.length)))){
df = df.withColumn(dt._1,df(dt._1).cast("String"))
}
}