Scala 中的 foldLeft 如何在 DataFrame 上工作?

Met*_*ata 9 scala

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

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

List(1,3,9).foldLeft(100)((x,y) => x+y)
Run Code Online (Sandbox Code Playgroud)

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", "")) }
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我从 dataFrame:yearDF中获取了 String 列,它保存在foldLeft. 我对 中使用的函数有以下疑问foldLeft

  1. tempDF 持有什么价值?如果它与 yearDF 相同,它如何映射到 yearDF ?
  2. 如果withColumns在函数中使用并将结果添加到yearDF,为什么它不创建重复列时

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

Leo*_*o C 14

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

List(3, 2, 1).foldLeft("abcde")((acc, x) => acc.take(x))
Run Code Online (Sandbox Code Playgroud)

如果您仔细查看(acc, x) => acc.take(x)函数在每次迭代中的作用,foldLeft则与以下内容没有区别:

"abcde".take(3).take(2).take(1)
// Result: "a"
Run Code Online (Sandbox Code Playgroud)

回到foldLeft你的 DataFrame :

stringColumns.foldLeft(yearDF){ (tempdf, colName) =>
  tempdf.withColumn(colName, regexp_replace(col(colName), "\n", ""))
}
Run Code Online (Sandbox Code Playgroud)

同样,它与以下内容没有区别:

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", ""))
Run Code Online (Sandbox Code Playgroud)
  1. tempDF 持有什么价值?如果它与 yearDF 相同,它如何映射到 yearDF ?

在每次迭代 (i = 0, 1, 2, ...) 中,tempDF保存一个从应用转换而来的新数据帧withColumn(stringColumns(i), ...),从yearDF

  1. 如果在函数中使用了 withColumns 并将结果添加到 yearDF 中,那么它为什么不创建重复列

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