我需要将 RDBMS 表摄取到 Hive 中,并且在使用 regex_replace 模式将其插入 Hive 表之前,我必须清理其 String 列中的数据。在无法理解如何将它应用于我的 dataFrame 之后,我终于在 Scala 中遇到了一个方法,它是 foldLeft ,它有助于满足要求。

我了解 foldLeft 如何处理集合,例如:

List(1,3,9).foldLeft(100)((x,y) => x+y)

foldLeft 接受参数:initialValue 和一个函数。它将函数的结果添加到累加器中。在上述情况下,结果为:113。

但是当涉及到数据框时,我无法理解它是如何工作的。
val stringColumns = yearDF.schema.fields.filter(_.dataType == StringType).map(_.name)
val finalDF = stringColumns.foldLeft(yearDF){ (tempdf, colName) => tempdf.withColumn(colName, regexp_replace(col(colName), "\n", "")) }

在上面的代码中,我从 dataFrame: yearDF 获得了 String 列,它保存在 foldLeft 的累加器中。我对 foldLeft 中使用的函数有以下疑问:
  • tempDF 持有什么值?如果它与 yearDF 相同,它如何映射到 yearDF ?
  • 如果在函数中使用了 withColumns 并将结果添加到
    yearDF,为什么在
  • 时不创建重复列

    谁能解释一下,以便我可以更好地了解foldLeft。

    最佳答案

    考虑一个与您的 DataFrame 版本更相似的简单 foldLeft 示例:

    List(3, 2, 1).foldLeft("abcde")((acc, x) => acc.take(x))
    

    如果仔细观察 (acc, x) => acc.take(x) 函数在每次迭代中的作用,foldLeft 与以下内容没有区别:
    "abcde".take(3).take(2).take(1)
    // Result: "a"
    

    回到 DataFrame 的 foldLeft:
    stringColumns.foldLeft(yearDF){ (tempdf, colName) =>
      tempdf.withColumn(colName, regexp_replace(col(colName), "\n", ""))
    }
    

    同样,它与以下内容没有区别:
    val sz = stringColumns.size
    
    yearDF.
      withColumn(stringColumns(0), regexp_replace(col(stringColumns(0)), "\n", "")).
      withColumn(stringColumns(1), regexp_replace(col(stringColumns(1)), "\n", "")).
      ...
      withColumn(stringColumns(sz - 1), regexp_replace(col(stringColumns(sz - 1)), "\n", ""))
    



    在每次迭代 (i = 0, 1, 2, ...) 中,tempDF 保存了一个新的 DataFrame,它是通过应用 withColumn(stringColumns(i), ...) 转换而来的,从 yearDF 开始



    withColumn(stringColumns(i), regexp_replace(col(stringColumns(i)), "\n", "")) ,方法 withColumn 创建一个新的 DataFrame,“添加”一个与它派生的 stringColumns(i) 列同名的列,从而基本上产生一个新的 DataFrame,其列列表与原始 yearDF 相同。

    关于scala - Scala 中的 foldLeft 如何在 DataFrame 上工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52025223/

    10-12 16:36