【问题标题】:How to compute cumulative sum on multiple float columns?如何计算多个浮点列的累积和?
【发布时间】:2020-01-31 12:43:50
【问题描述】:

我在 Dataframe 中有 100 个浮点列,按日期排序。

ID   Date         C1       C2 ....... C100
1     02/06/2019   32.09  45.06         99
1     02/04/2019   32.09  45.06         99
2     02/03/2019   32.09  45.06         99
2     05/07/2019   32.09  45.06         99

我需要根据id和日期在累计和中得到C1到C100。

目标数据框应如下所示:

ID   Date         C1       C2 ....... C100
1     02/04/2019   32.09  45.06         99
1     02/06/2019   64.18  90.12         198
2     02/03/2019   32.09  45.06         99
2     05/07/2019   64.18  90.12         198

我想在不从 C1-C100 循环的情况下实现这一点。

一列的初始代码:

var DF1 =  DF.withColumn("CumSum_c1", sum("C1").over(
         Window.partitionBy("ID")
        .orderBy(col("date").asc)))

我在这里发现了一个类似的问题,但他手动为两列做了:Cumulative sum in Spark

【问题讨论】:

  • 你得到这个问题的答案了吗?

标签: scala apache-spark apache-spark-sql


【解决方案1】:

这是foldLeft 的经典用法。让我们先生成一些数据:

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

val df = spark.range(1000)
            .withColumn("c1", 'id + 3)
            .withColumn("c2", 'id % 2 + 1)
            .withColumn("date", monotonically_increasing_id)
            .withColumn("id", 'id % 10 + 1)

// We will select the columns we want to compute the cumulative sum of.       
val columns = df.drop("id", "date").columns

val w = Window.partitionBy(col("id")).orderBy(col("date").asc) 

val results = columns.foldLeft(df)((tmp_, column) => tmp_.withColumn(s"cum_sum_$column", sum(column).over(w)))

results.orderBy("id", "date").show
// +---+---+---+-----------+----------+----------+
// | id| c1| c2|       date|cum_sum_c1|cum_sum_c2|
// +---+---+---+-----------+----------+----------+
// |  1|  3|  1|          0|         3|         1|
// |  1| 13|  1|         10|        16|         2|
// |  1| 23|  1|         20|        39|         3|
// |  1| 33|  1|         30|        72|         4|
// |  1| 43|  1|         40|       115|         5|
// |  1| 53|  1| 8589934592|       168|         6|
// |  1| 63|  1| 8589934602|       231|         7|

【讨论】:

    【解决方案2】:

    这是另一种使用简单选择表达式的方法:

    val w = Window.partitionBy($"id").orderBy($"date".asc).rowsBetween(Window.unboundedPreceding, Window.currentRow) 
    
    // get columns you want to sum
    val columnsToSum = df.drop("ID", "Date").columns
    
    // map over those columns and create new sum columns
    val selectExpr = Seq(col("ID"), col("Date")) ++ columnsToSum.map(c => sum(col(c)).over(w).alias(c)).toSeq
    
    df.select(selectExpr:_*).show()
    

    给予:

    +---+----------+-----+-----+----+                                               
    | ID|      Date|   C1|   C2|C100|
    +---+----------+-----+-----+----+
    |  1|02/04/2019|32.09|45.06|  99|
    |  1|02/06/2019|64.18|90.12| 198|
    |  2|02/03/2019|32.09|45.06|  99|
    |  2|05/07/2019|64.18|90.12| 198|
    +---+----------+-----+-----+----+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-11
      • 2021-05-11
      • 2016-07-23
      • 2020-12-17
      • 2015-09-07
      • 2013-01-26
      • 2014-02-16
      • 2017-10-05
      相关资源
      最近更新 更多