Python 具有动态滞后的窗函数

Python 具有动态滞后的窗函数,python,apache-spark,pyspark,apache-spark-sql,window-functions,Python,Apache Spark,Pyspark,Apache Spark Sql,Window Functions,我正在查看Spark SQL中Spark数据帧的窗口滑动函数 我有一个数据框,其中包含id、month和volume列 id month volume new_col 1 201601 100 0 1 201602 120 100 1 201603 450 220 1 201604 200 670 1 201605 121 870 现在我想添加一个名为new\u col的新列

我正在查看Spark SQL中Spark数据帧的窗口滑动函数

我有一个数据框,其中包含
id
month
volume

id       month   volume new_col
1        201601  100     0
1        201602  120   100
1        201603  450   220
1        201604  200   670
1        201605  121   870
现在我想添加一个名为
new\u col
的新列,
new\u col
的值是当前行之前
volume
new\u col
的总和,如上所示。
new\u col
第一行的值将为零

我使用PySpark在下面的选项中尝试使用窗口函数
lag
。但是我发现
new\u col
列将被递归使用。仅使用
lag
功能的方法无法做到这一点:

window = Window.partitionBy(F.col('id')).orderBy(F.col('month').asc())
df.withColumn('new_col', F.lag(col('volume'), 1).over(window) + F.lag(col('new_col'), 1).over(window))

有没有一种方法可以通过使用窗口函数来动态延迟
新列
?或者还有其他好的解决方案吗?

您可以在窗口上使用
lag
sum
来实现这一点<如果在窗口上使用,代码>总和将自动计算总和。下面的代码将首先滞后于
volume
列,然后取其总和,但也可以按相反的顺序进行操作

window = Window.partitionBy(F.col('id')).orderBy(F.col('month').asc())
df.withColumn('new_col', F.sum(F.lag(col('volume'), 1, 0).over(window)).over(window))

您可以在窗口上使用
lag
sum
来实现这一点<如果在窗口上使用,代码>总和将自动计算总和。下面的代码将首先滞后于
volume
列,然后取其总和,但也可以按相反的顺序进行操作

window = Window.partitionBy(F.col('id')).orderBy(F.col('month').asc())
df.withColumn('new_col', F.sum(F.lag(col('volume'), 1, 0).over(window)).over(window))

可以使用嵌套窗口函数

>>> from pyspark.sql.window import Window
>>> import pyspark.sql.functions as F
>>> 
>>> data = sc.parallelize([
...     (1,'201601',100),
...     (1,'201602',120),
...     (1,'201603',450),
...     (1,'201604',200),
...     (1,'201605',121)])
>>> col = ['id','month', 'volume']
>>> 
>>> df = spark.createDataFrame(data, col)
>>> df.show()
+---+------+------+
| id| month|volume|
+---+------+------+
|  1|201601|   100|
|  1|201602|   120|
|  1|201603|   450|
|  1|201604|   200|
|  1|201605|   121|
+---+------+------+

>>> window1 = Window.partitionBy('id').orderBy('month')
>>> window2 = Window.partitionBy('id').orderBy('month').rangeBetween(Window.unboundedPreceding, 0)
>>> df = df.withColumn('new_col', F.sum(F.lag('volume').over(window1)).over(window2)).na.fill({'new_col': 0})
>>> df.show()
+---+------+------+-------+                                                     
| id| month|volume|new_col|
+---+------+------+-------+
|  1|201601|   100|      0|
|  1|201602|   120|    100|
|  1|201603|   450|    220|
|  1|201604|   200|    670|
|  1|201605|   121|    870|
+---+------+------+-------+

可以使用嵌套窗口函数

>>> from pyspark.sql.window import Window
>>> import pyspark.sql.functions as F
>>> 
>>> data = sc.parallelize([
...     (1,'201601',100),
...     (1,'201602',120),
...     (1,'201603',450),
...     (1,'201604',200),
...     (1,'201605',121)])
>>> col = ['id','month', 'volume']
>>> 
>>> df = spark.createDataFrame(data, col)
>>> df.show()
+---+------+------+
| id| month|volume|
+---+------+------+
|  1|201601|   100|
|  1|201602|   120|
|  1|201603|   450|
|  1|201604|   200|
|  1|201605|   121|
+---+------+------+

>>> window1 = Window.partitionBy('id').orderBy('month')
>>> window2 = Window.partitionBy('id').orderBy('month').rangeBetween(Window.unboundedPreceding, 0)
>>> df = df.withColumn('new_col', F.sum(F.lag('volume').over(window1)).over(window2)).na.fill({'new_col': 0})
>>> df.show()
+---+------+------+-------+                                                     
| id| month|volume|new_col|
+---+------+------+-------+
|  1|201601|   100|      0|
|  1|201602|   120|    100|
|  1|201603|   450|    220|
|  1|201604|   200|    670|
|  1|201605|   121|    870|
+---+------+------+-------+

非常感谢。如果我想做“乘法”,而不是求和。我该怎么办?函数包中没有F.multiply函数。阿里,你能看看
https://stackoverflow.com/questions/54493277/dynamic-filtering-a-pyspark-dataframe
?我还没有发布,但我很好奇,我们如何使用dynamic
lead
或其他方法解决这个问题。谢谢你的考虑,非常感谢。如果我想做“乘法”,而不是求和。我该怎么办?函数包中没有F.multiply函数。阿里,你能看看
https://stackoverflow.com/questions/54493277/dynamic-filtering-a-pyspark-dataframe
?我还没有发布,但我很好奇,我们如何使用dynamic
lead
或其他方法解决这个问题。谢谢你的考虑。