首页 文章

在spark Dataframe中使用arraytype

提问于
浏览
0

我的要求是将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中的列保持不变,尽管它们是十进制类型 . 请帮助,我如何循环嵌套元素并将其转换为字符串 . 这是我的数据帧的架构:

scala> df.schema res77:org.apache.spark.sql.types.StructType = StructType(StructField(mstr_prov_id,StringType,true),StructField(prov_ctgry_cd,StringType,true),StructField(prov_orgnl_efctv_dt,TimestampType,true),StructField (prov_trmntn_dt,TimestampType,true),StructField(prov_trmntn_rsn_cd,StringType,true),StructField(npi_rqrd_ind,StringType,true),StructField(prov_stts_aray_txt,ArrayType(StructType(StructField(PROV_STTS_KEY,DecimalType(22,0),true),StructField( PROV_STTS_EFCTV_DT,TimestampType,true),StructField(PROV_STTS_CD,StringType,true),StructField(PROV_STTS_TRMNTN_DT,TimestampType,true),StructField(PROV_STTS_TRMNTN_RSN_CD,StringType,true)),true),true))

3 回答

  • 0

    如果你使用的是火花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版本低于上面提到的并且因为你将遇到struct结构列中的timestamp数据类型

    TimestampType(类org.apache.spark.sql.types.TimestampType $)scala.MatchError:TimestampType(类org.apache.spark.sql.types.TimestampType $)

    casting structs fails on Timestamp fields并解决cast struct with timestamp field fails

  • 0

    您还可以投射复杂类型,例如如果你有像这个架构的数据帧:

    root
     |-- arr: array (nullable = true)
     |    |-- element: struct (containsNull = true)
     |    |    |-- i: decimal(22,0) (nullable = true)
     |    |    |-- j: double (nullable = false)
    

    您可以通过执行以下操作来强制转换所有十进制类型的数组元素(字段 i n此示例):

    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)
    

    编辑:如果你事先不知道架构,你可以用 string 替换原始架构中的 decimal

    val arraySchema = df.schema.fields(0).dataType.simpleString
    val castedSchema = arraySchema.replaceAll("decimal\\(.*\\)","string")
    
    df
      .select($"arr".cast(castedSchema))
      .show()
    
  • 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"))  
      }
    }
    

相关问题