Skip to main content
 首页 » 编程设计

python之Pyspark之具有重置条件的累积和

2024年09月03日35jiqing9006

我有这个数据框

+---+----+---+ 
|  A|   B|  C| 
+---+----+---+ 
|  0|null|  1| 
|  1| 3.0|  0| 
|  2| 7.0|  0| 
|  3|null|  1| 
|  4| 4.0|  0| 
|  5| 3.0|  0| 
|  6|null|  1| 
|  7|null|  1| 
|  8|null|  1| 
|  9| 5.0|  0| 
| 10| 2.0|  0| 
| 11|null|  1| 
+---+----+---+ 

我需要做的是对 C 列中的值进行累加,直到下一个值为零。

预期输出:

+---+----+---+----+ 
|  A|   B|  C|   D| 
+---+----+---+----+ 
|  0|null|  1|   1| 
|  1| 3.0|  0|   0| 
|  2| 7.0|  0|   0| 
|  3|null|  1|   1| 
|  4| 4.0|  0|   0| 
|  5| 3.0|  0|   0| 
|  6|null|  1|   1| 
|  7|null|  1|   2| 
|  8|null|  1|   3| 
|  9| 5.0|  0|   0| 
| 10| 2.0|  0|   0| 
| 11|null|  1|   1| 
+---+----+---+----+ 

重现数据框:

from pyspark.shell import sc 
from pyspark.sql import Window 
from pyspark.sql.functions import lag, when, sum 
 
x = sc.parallelize([ 
    [0, None], [1, 3.], [2, 7.], [3, None], [4, 4.], 
    [5, 3.], [6, None], [7, None], [8, None], [9, 5.], [10, 2.], [11, None]]) 
x = x.toDF(['A', 'B']) 
 
# Transform null values into "1" 
x = x.withColumn('C', when(x.B.isNull(), 1).otherwise(0)) 

请您参考如下方法:

创建一个临时列 (grp),每次列 C 等于 0(重置条件)时计数器递增并使用这是您的累计总和的分区列。

import pyspark.sql.functions as f 
from pyspark.sql import Window 
 
x.withColumn( 
    "grp",  
    f.sum((f.col("C") == 0).cast("int")).over(Window.orderBy("A")) 
).withColumn( 
    "D", 
    f.sum(f.col("C")).over(Window.partitionBy("grp").orderBy("A")) 
).drop("grp").show() 
#+---+----+---+---+ 
#|  A|   B|  C|  D| 
#+---+----+---+---+ 
#|  0|null|  1|  1| 
#|  1| 3.0|  0|  0| 
#|  2| 7.0|  0|  0| 
#|  3|null|  1|  1| 
#|  4| 4.0|  0|  0| 
#|  5| 3.0|  0|  0| 
#|  6|null|  1|  1| 
#|  7|null|  1|  2| 
#|  8|null|  1|  3| 
#|  9| 5.0|  0|  0| 
#| 10| 2.0|  0|  0| 
#| 11|null|  1|  1| 
#+---+----+---+---+