【问题标题】:apply window function to multiple columns将窗口函数应用于多列
【发布时间】:2020-10-18 18:04:10
【问题描述】:

我有一个超过 20 列的 DF。对于每一列,我需要找到前导值并将其添加到结果中。

我一直在使用 with 列。

df
.withColumn("lead_col1", lead("col1").over(window))
.withColumn("lead_col2", lead("col2").over(window))
.withColumn("lead_col3", lead("col3").over(window))

还有 17 行这样的。有没有办法使用更少的代码来做到这一点?我尝试使用this 示例,但它不起作用。

【问题讨论】:

  • 如果你使用的是scala,你可以有列表列并使用foldleft添加列。

标签: apache-spark apache-spark-sql


【解决方案1】:

查看下面的代码,比foldLeft快。

import org.apache.spark.sql.expressions._

val windowSpec = ...
val windowColumns = Seq(
                         ("lead_col1", "col1"),
                         ("lead_col2","col2"),
                         ("lead_col3","col3")
                    ).map(c => lead(col(c._2),1).over(windowSpec).as(c._1))

val windowColumns = df.columns ++ windowColumns

windowColumns 应用于DataFrame。

df.select(windowColumns:_*).show(false)

【讨论】:

  • 这个例子很有趣,但它不起作用。或者更确切地说,选择只适用于第一个windowColumns。其中只有一半需要的列。此外,执行计划通常是相同的,但有两个额外的步骤+- *Project [col1#0... ]。为什么你认为它应该工作得更快?
  • 查看这篇文章stackoverflow.com/questions/62487649/… 进行性能比较。我添加了代码作为示例。
  • 还有这个例子stackoverflow.com/questions/63026858/… .. foldleft 比选择函数慢
【解决方案2】:

就像 Sath 建议的那样,foldleft 有效。

  val columns = df.columns
  columns.foldLeft(df){(tempDF, colName) =>
    tempDF.withColumn("lag_" + colName, lag($"$colName", 1).over(window))}

【讨论】:

    猜你喜欢
    • 2017-09-18
    • 2021-04-27
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多