【问题标题】:How does foldLeft in Scala work on DataFrame?Scala 中的 foldLeft 如何在 DataFrame 上工作?
【发布时间】:2020-07-20 17:47:06
【问题描述】:

我需要将 RDBMS 表摄取到 Hive 中,并且在使用 regex_replace 模式将其插入 Hive 表之前,我必须清理其字符串列中的数据。在无法理解如何将它应用到我的 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中得到了String列:yearDF,它保存在foldLeft的累加器中。我对foldLeft中使用的函数有以下疑惑:

  1. tempDF 的值是多少?如果和yearDF一样,怎么映射到yearDF?
  2. 如果在函数中使用withColumns并将结果添加到 yearDF,为什么不创建重复的列时

谁能解释一下,让我对 foldLeft 有更好的了解。

【问题讨论】:

    标签: scala


    【解决方案1】:

    考虑一个与您的 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"
    

    返回 foldLeft 获取您的 DataFrame:

    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", ""))
    
    1. tempDF 的值是多少?如果和yearDF一样,怎么映射到yearDF?

    在每次迭代(i = 0, 1, 2, ...)中,tempDF 持有一个从应用withColumn(stringColumns(i), ...) 转换而来的新DataFrame,从yearDF 开始

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

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

    【讨论】:

    【解决方案2】:

    只是为了让你的第二个问题更清楚一点。 当您使用现有列名调用 dataframe.withColumn() 时,它会返回一个新数据框,其中原始列替换为新列。

    无论您是否处于 foldLeft 操作的上下文中,都会发生这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-09
      • 2019-07-28
      • 1970-01-01
      • 2013-06-12
      • 2021-08-17
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多