Python 3.x 使用pyspark跟踪具有附加条件的前一行值

Python 3.x 使用pyspark跟踪具有附加条件的前一行值,python-3.x,apache-spark,pyspark,apache-spark-sql,pyspark-sql,Python 3.x,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Sql,我正在使用pyspark生成一个数据帧,在该数据帧中,仅当amt=0时,我需要使用前一行的“amt”值更新“amt”列 例如,下面是我的数据帧 +---+-----+ | id|amt | +---+-----+ | 1| 5| | 2| 0| | 3| 0| | 4| 6| | 5| 0| | 6| 3| +---+-----+ 现在,我希望创建以下DF。无论何时amt=0,modi_amt col将包含前一行的非零值,否则不进行更改 +--

我正在使用pyspark生成一个数据帧,在该数据帧中,仅当amt=0时,我需要使用前一行的“amt”值更新“amt”列

例如,下面是我的数据帧

+---+-----+
| id|amt  |
+---+-----+
|  1|    5|
|  2|    0|
|  3|    0|
|  4|    6|
|  5|    0|
|  6|    3|
+---+-----+
现在,我希望创建以下DF。无论何时amt=0,modi_amt col将包含前一行的非零值,否则不进行更改

+---+-----+----------+
| id|amt  |modi_amt  |
+---+-----+----------+
|  1|    5|         5|
|  2|    0|         5|
|  3|    0|         5|
|  4|    6|         6|
|  5|    0|         6|
|  6|    3|         3|
+---+-----+----------+
我能够获得前几行的值,但需要对显示多个0 amt的行的帮助(例如,id=2,3)

我正在使用的代码:

from pyspark.sql.window import Window
my_window = Window.partitionBy().orderBy("id")
DF= DF.withColumn("prev_amt", F.lag(DF.amt).over(my_window))
DF= DF.withColumn("modi_amt",when(DF.amt== 0,DF.prev_amt).otherwise(DF.amt)).drop('prev_amt')
我得到下面的DF

+---+-----+----------+
| id|amt  |modi_amt  |
+---+-----+----------+
|  1|    5|         5|
|  2|    0|         5|
|  3|    0|         0|
|  4|    6|         6|
|  5|    0|         6|
|  6|    3|         3|
+---+-----+----------+

基本上,id 3也应该有modi_amt=5,我已经使用了下面的方法来获得输出,它工作正常

from pyspark.sql.window import Window
my_window = Window.partitionBy().orderBy("id")
# this will hold the previous col value
DF= DF.withColumn("prev_amt", F.lag(DF.amt).over(my_window))

# this will replace the amt 0 with previous column value, but not consecutive rows having 0 amt.  
DF = DF.withColumn("amt_adjusted",when(DF.prev_amt == 0,DF.prev_OffSet).otherwise(DF.amt))

# define null for the rows where both amt and amt_adjusted are having 0 (logic for consecutive rows having 0 amt)
DF = DF.withColumn('zeroNonZero', when((DF.amt== 0)&(DF.amt_adjusted == 0),lit(None)).otherwise(DF.amt_adjusted))

# replace all null values with previous Non zero amt row value
DF= DF.withColumn('modi_amt',last("zeroNonZero", ignorenulls= True).over(Window.orderBy("id").rowsBetween(Window.unboundedPreceding,0)))

还有其他更好的方法吗

根据您自己的逻辑,id 3应为零,因为原始金额为零。逻辑是将任何金额=0替换为以前的非零值。这里id#1 amt=5,id#2和id#3都有amt=0,因此这两个id的modi#u amt可能是5的副本,我想你可以直接用null替换amt列中的0,然后使用last(),就像你所做的那样,我看不到先获取上一个amt值有什么用