首页 > 解决方案 > 将双列数组动态转换为嵌套火花数据框中的多列

问题描述

我当前的 DataFrame 如下所示:

{"id":"1","inputs":{"values":{"0.2":[1,1],"0.4":[1,1],"0.6":[1,1]}},"id1":[1,2]}

我想将此数据框转换为以下数据框:

{"id":"1", "v20":[1,1],"v40":[1,1],"v60":[1,1],"id1":[1,2]}

这意味着,每个 'values' 数组的项目(0.2、0.4 和 0.6)将乘以 100,以字母 'v' 开头,并提取到单独的列中。

为了实现这一点,代码看起来如何。我已经尝试过withColumn但无法做到这一点。

标签: scalaapache-spark

解决方案


我会将列名拆分器更改的逻辑分为两部分,一个是数值,另一个是不变的。

def stringDecimalToVNumber(colName:String): String =
  "v" + (colName.toFloat * 100).toInt.toString

并形成一个根据情况变换的单一函数

val floatRegex = """(\d+\.?\d*)""".r
def transformColumnName(colName:String): String = colName match {
  case floatRegex(v) => stringDecimalToVNumber(v) //it's a float, transform it
  case x => x // keep it

现在我们有了转换列末尾的功能,让我们动态选择模式。

val flattenDF = df.select("id","inputs.values.*")

val finalDF = flattenDF
  .schema.names
  .foldLeft(flattenDF)((dfacum,x) => {
    val newName = transformColumnName(x)
    if (newName == x)
      dfacum // the name didn't need to be changed
    else 
      dfacum.withColumnRenamed(x, transformColumnName(x))
  })

这会将inputs.values中的所有列动态转换为新名称,并将它们放在id旁边。


推荐阅读