Apache spark 如何使用spark window函数将上一行的更改级联到下一行

Apache spark 如何使用spark window函数将上一行的更改级联到下一行,apache-spark,pyspark,Apache Spark,Pyspark,我尝试使用窗口函数,根据以前的值动态计算当前值 rowID | value ------------------ 1 | 5 2 | 7 3 | 6 逻辑: If value > pre_value then value 所以在第2行中,因为7>5,所以value变为5。 最终结果应该是 rowID | value ------------------ 1 | 5 2 | 5 3

我尝试使用窗口函数,根据以前的值动态计算当前值

    rowID | value
------------------
     1    | 5
     2    | 7
     3    | 6
逻辑:

If value > pre_value then value
所以在第2行中,因为7>5,所以
value
变为5。 最终结果应该是

    rowID | value
------------------
     1    | 5
     2    | 5
     3    | 5
但是,使用
lag().over(w)
得出的结果如下

    rowID | value
------------------
     1    | 5
     2    | 5
     3    | 6
它将第三行值6与“7”进行比较,而不是与新值“5”进行比较

如何实现这一目标,有什么建议吗

df.show()
#exampledataframe
+-----+-----+
|rowID|value|
+-----+-----+
|    1|    5|
|    2|    7|
|    3|    6|
|    4|    9|
|    5|    4|
|    6|    3|
+-----+-----+
您所需的逻辑对于窗口函数来说过于动态,因此,我们必须逐行更新我们的值。一种解决方案是在收集的列表上使用普通python
udf
,然后在应用
udf
后分解。如果有相对较小的数据,这应该很好。(spark2.4因为
数组\u-zip

更新:

更好的是,由于您有5000个组,使用矢量化的udf(分组映射)
应该对处理有很大帮助。您不必收集包含5000个整数的列表,也不必分解或使用透视。我认为这应该是最佳的解决方案<代码>spark2.3+可用的熊猫UDAF

下面的GroupBy为空,但您可以在其中添加分组列


@fromSAS2Spark-您的值列是否已按升序排序?或者是否需要在行中显示最小值。i、 “无论它发现什么地方小,它都应该填满那个最小的地方。”古坦普拉丹谢谢你。我不想用最小值填充,我想用以前可能已更新的值填充。这里的例子很简单,但实际上我有32行,也许中间3行只需要更改,我认为你们应该使用udf。每一行的逻辑都可能是动态的,窗口函数无法做到这一点。谢谢。这是我之前的最后一个选项,因为问题的实际大小约为500万行,分组为5000行。我不太确定内存利用率将如何工作。我的最后一个选择是使用pivot并将这些行转换为列,然后应用类似的逻辑。我也不知道这是否可行。我要两个都试一下。再次感谢您确认窗口功能不能被禁用used@fromSAS2Spark我已经更新了一个用户定义的聚合函数,该函数基本上使用spark数据组的矢量化操作。我认为这将大大超过所有其他选项,请尝试如何确保数据有序,如果我执行显式排序,则两个UDF都不需要排序,它们可以按原样应用。如果你的意思是在udf之后,那就看你了
from pyspark.sql import functions as F
from pyspark.sql.types import *
def add_one(a):
    for i in range(1,len(a)):
       if a[i]>a[i-1]:
           a[i]=a[i-1]
    return a
udf1= F.udf(add_one, ArrayType(IntegerType()))
df.agg(F.collect_list("rowID").alias("rowID"),F.collect_list("value").alias("value"))\
  .withColumn("value", udf1("value"))\
  .withColumn("zipped", F.explode(F.arrays_zip("rowID","value"))).select("zipped.*").show()

+-----+-----+
|rowID|value|
+-----+-----+
|    1|    5|
|    2|    5|
|    3|    5|
|    4|    5|
|    5|    4|
|    6|    3|
+-----+-----+
from pyspark.sql.functions import pandas_udf, PandasUDFType
@pandas_udf(df.schema, PandasUDFType.GROUPED_MAP)
def grouped_map(df1):
   for i in range(1, len(df1)):
        if df1.loc[i, 'value']>df1.loc[i-1,'value']:
           df1.loc[i,'value']=df1.loc[i-1,'value']

   return df1
df.groupby().apply(grouped_map).show()

+-----+-----+
|rowID|value|
+-----+-----+
|    1|    5|
|    2|    5|
|    3|    5|
|    4|    5|
|    5|    4|
|    6|    3|
+-----+-----+