【问题标题】:Populate a column based on previous value and row Pyspark根据先前的值和行 Pyspark 填充列
【发布时间】:2021-09-01 13:27:54
【问题描述】:

我有一个包含 5 列组、日期、a、b 和 c 的 spark 数据框,我想要执行以下操作:

给定 df

group    date      a    b      c
  a     2018-01    2    3     10
  a     2018-02    4    5     null
  a     2018-03    2    1     null

预期输出

group    date      a    b      c
  a     2018-01    2    3     10
  a     2018-02    4    5     10*3+2=32
  a     2018-03    2    1     32*5+4=164

对于每个组,通过 b * c + a 计算 c 并将输出用作下一行的 c。

我尝试使用 Lag 和窗口函数,但找不到正确的方法。

【问题讨论】:

  • 一个后续问题,如果我需要当前行 b 值,我可以使用带有最后一个值的示例逻辑吗?或者它不会工作?具体到这个例子而不是 10*3+2=32 我会做 (10*3+2)/5=6.4 (在这个例子中 b=5)

标签: apache-spark pyspark apache-spark-sql


【解决方案1】:

在窗口中,您无法访问当前要计算的列的结果。这将迫使 Spark 按顺序进行计算,应该避免。另一种方法是将递归计算c_n = func(c_(n-1))转换为只使用ab的(常数)值和c的第一个值的公式:

这个公式的所有输入值都可以用一个窗口收集,公式本身实现为udf

from pyspark.sql import functions as F
from pyspark.sql import types as T
from pyspark.sql import Window

df = ...
w=Window.partitionBy('group').orderBy('date')
df1 = df.withColumn("la", F.collect_list("a").over(w)) \
  .withColumn("lb", F.collect_list("b").over(w)) \
  .withColumn("c0", F.first("c").over(w))

import numpy as np

def calc_c(c0, a, b):
  if c0 is None:
    return 0.0
  if len(a) == 1:
    return float(c0)
  e1 = c0 * np.prod(b[:-1])
  e2 = 0.0
  for i,an in enumerate(a[:-1]):
    e2 = e2 + an * np.prod(b[i+1:-1])
  return float(e1 + e2)


calc_c_udf= F.udf(calc_c, T.DoubleType())

df1.withColumn("result", calc_c_udf("c0", "la", "lb")) \
  .show()

输出:

+-----+-------+---+---+----+---------+---------+---+------+
|group|   date|  a|  b|   c|       la|       lb| c0|result|
+-----+-------+---+---+----+---------+---------+---+------+
|    a|2018-01|  2|  3|  10|      [2]|      [3]| 10|  10.0|
|    a|2018-02|  4|  5|null|   [2, 4]|   [3, 5]| 10|  32.0|
|    a|2018-03|  2|  1|null|[2, 4, 2]|[3, 5, 1]| 10| 164.0|
+-----+-------+---+---+----+---------+---------+---+------+

【讨论】:

  • 好东西……你把我吃掉了
  • 哇...太棒了!
  • 太棒了!非常感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 2017-10-07
相关资源
最近更新 更多