Pyspark: за каждый месяц делайте кумулятивную сумму за предыдущие 3 месяца - PullRequest
2 голосов
/ 07 апреля 2020

Я использую PYSPARK и пытаюсь составить кумулятивную сумму за последние 3 месяца из указанного c месяца:

Пример:

Month   Value
Jan/19    1
Feb/19    0
Mar/19    4
Apr/19    5
May/19    0
Jun/19   10

Так что совокупная сумма за каждый месяц предыдущих месяцев будет:

Month   Value
Jan/19    1
Feb/19  1 + 0 = 1
Mar/19  1+0+4 = 5
Apr/19  0+4+5 = 9
May/19  4+5+0 = 9
Jun/19  5+0+10 = 15 

Я почти уверен, что мне нужно использовать функции окон и разделов, но я не знаю, как это настроить.

Может ли кто-нибудь помочь мне в этом?

Спасибо

1 Ответ

1 голос
/ 08 апреля 2020

Пример кадра данных:

df.show()
+------+-----+
| Month|Value|
+------+-----+
|Jan/19|    1|
|Feb/19|    0|
|Mar/19|    4|
|Apr/19|    5|
|May/19|    0|
|Jun/19|   10|
+------+-----+

Вы можете использовать функцию window, но вам необходимо преобразовать month столбец в правильный timestamp формат, а затем приведите его к long для вычисления range(3months) на основе unix time или timestamp in seconds. Вы можете разделить ваши столбцы группировки в ваших реальных данных. ( 86400 - 1 день в секундах ).

from pyspark.sql import functions as F
from pyspark.sql.window import Window

w=Window().orderBy(F.col("Month").cast("long")).rangeBetween(-(86400*89), 0)
df\
.withColumn("Month", F.to_timestamp("Month","MMM/yy"))\
.withColumn("Sum", F.sum("Value").over(w)).show()

+-------------------+-----+---+
|              Month|Value|Sum|
+-------------------+-----+---+
|2019-01-01 00:00:00|    1|  1|
|2019-02-01 00:00:00|    0|  1|
|2019-03-01 00:00:00|    4|  5|
|2019-04-01 00:00:00|    5|  9|
|2019-05-01 00:00:00|    0|  9|
|2019-06-01 00:00:00|   10| 15|
+-------------------+-----+---+

Если вы хотите go назад 3 months only в each year. Значение Jan/19 будет иметь только Jan/19 значение . В этом случае вам следует использовать partitionBy из Year и orderBy month number и rangeBetween -2 and 0.

w=Window().partitionBy(F.year("Month")).orderBy(F.month("Month")).rangeBetween(-2, 0)
df\
.withColumn("Month", F.to_timestamp("Month","MMM/yy"))\
.withColumn("Sum", F.sum("Value").over(w)).show()

+-------------------+-----+---+
|              Month|Value|Sum|
+-------------------+-----+---+
|2019-01-01 00:00:00|    1|  1|
|2019-02-01 00:00:00|    0|  1|
|2019-03-01 00:00:00|    4|  5|
|2019-04-01 00:00:00|    5|  9|
|2019-05-01 00:00:00|    0|  9|
|2019-06-01 00:00:00|   10| 15|
+-------------------+-----+---+
...