使用pyspark对列上的值求和

使用pyspark对列上的值求和,pyspark,apache-spark-sql,Pyspark,Apache Spark Sql,我有一个场景,我有两个表,一个表有天,另一个表有值。所以从有天数的表中,我需要将另一个表的值和天数相加。 数据帧 dataframe1 df1 = spark.createDataFrame( [ ('ll',5) ('yy',6) ], ('x','days') ) dataframe2 df = spark.createDataFrame( [ ('ll','2020-01-05','

我有一个场景,我有两个表,一个表有天,另一个表有值。所以从有天数的表中,我需要将另一个表的值和天数相加。 数据帧

dataframe1
df1 = spark.createDataFrame(
     [
     ('ll',5)
     ('yy',6)
     ],
     ('x','days')
    )
  dataframe2 
  df = spark.createDataFrame(
        [
            ('ll','2020-01-05','1','10','50'),
    ('ll','2020-01-06','1','10'),
    ('ll','2020-01-07','1','10'),
    ('ll','2020-01-08','1','10'),
    ('ll','2020-01-09','1','10'),
    ('ll','2020-01-10','1','10'),
    ('ll','2020-01-11','1','20'),
    ('ll','2020-01-12','1','10'),
    ('ll','2020-01-05','2','30'),
    ('ll','2020-01-06','2','30'),
    ('ll','2020-01-07','2','30'),
    ('ll','2020-01-08','2','40'),
    ('ll','2020-01-09','2','30'),
    ('ll','2020-01-10','2','10'),
    ('ll','2020-01-11','2','10'),
    ('ll','2020-01-12','2','10'),
    ('yy','2020-01-05','1','20'),
    ('yy','2020-01-06','1','20'),
    ('yy','2020-01-07','1','20'),
    ('yy','2020-01-08','1','20'),
    ('yy','2020-01-09','1','20'),
    ('yy','2020-01-10','1','40'),
    ('yy','2020-01-11','1','20'),
    ('yy','2020-01-12','1','20'),
    ('yy','2020-01-05','2','40'),
    ('yy','2020-01-06','2','40'),
    ('yy','2020-01-07','2','40'),
    ('yy','2020-01-08','2','40'),
    ('yy','2020-01-09','2','40'),
    ('yy','2020-01-10','2','40'),
    ('yy','2020-01-11','2','60'),
    ('yy','2020-01-12','2','40')
        ],
        ('x','date','flag','value')
    )

                expected_dataframe = spark.createDataFrame(
        [
            ('ll','2020-01-05','1','10','50'),
    ('ll','2020-01-06','1','10','50'),
    ('ll','2020-01-07','1','10','60'),
    ('ll','2020-01-08','1','10','60'),
    ('ll','2020-01-09','1','10','50'),
    ('ll','2020-01-10','1','10','40'),
    ('ll','2020-01-11','1','20','30'),
    ('ll','2020-01-12','1','10','10'),
    ('ll','2020-01-05','2','30','170'),
    ('ll','2020-01-06','2','30','140'),
    ('ll','2020-01-07','2','30','120'),
    ('ll','2020-01-08','2','40','100'),
    ('ll','2020-01-09','2','30','60'),
    ('ll','2020-01-10','2','10','30'),
    ('ll','2020-01-11','2','10','20'),
    ('ll','2020-01-12','2','10','10'),
    ('yy','2020-01-05','1','20','140'),
    ('yy','2020-01-06','1','20','140'),
    ('yy','2020-01-07','1','20','140'),
    ('yy','2020-01-08','1','20','120'),
    ('yy','2020-01-09','1','20','100'),
    ('yy','2020-01-10','1','40','80'),
    ('yy','2020-01-11','1','20','40'),
    ('yy','2020-01-12','1','20','20'),
    ('yy','2020-01-05','2','40','240'),
    ('yy','2020-01-06','2','40','260'),
    ('yy','2020-01-07','2','40','260'),
    ('yy','2020-01-08','2','40','220'),
    ('yy','2020-01-09','2','40','180'),
    ('yy','2020-01-10','2','40','140'),
    ('yy','2020-01-11','2','60','100'),
    ('yy','2020-01-12','2','40','40')
        ],
        ('x','date','flag','value','result')
预期结果

    +---+----------+----+-----+------+
    |  x|      date|flag|value|result|
    +---+----------+----+-----+------+
    | ll|2020-01-05|   1|   10|    50|
    | ll|2020-01-06|   1|   10|    50|
    | ll|2020-01-07|   1|   10|    60|
    | ll|2020-01-08|   1|   10|    60|
    | ll|2020-01-09|   1|   10|    50|
    | ll|2020-01-10|   1|   10|    40|
    | ll|2020-01-11|   1|   20|    30|
    | ll|2020-01-12|   1|   10|    10|
    | ll|2020-01-05|   2|   30|   170|
    | ll|2020-01-06|   2|   30|   140|
    | ll|2020-01-07|   2|   30|   120|
    | ll|2020-01-08|   2|   40|   100|
    | ll|2020-01-09|   2|   30|    60|
    | ll|2020-01-10|   2|   10|    30|
    | ll|2020-01-11|   2|   10|    20|
    | ll|2020-01-12|   2|   10|    10|
    | yy|2020-01-05|   1|   20|   140|
    | yy|2020-01-06|   1|   20|   140|
    | yy|2020-01-07|   1|   20|   140|
    | yy|2020-01-08|   1|   20|   120|
    | yy|2020-01-09|   1|   20|   100|
    | yy|2020-01-10|   1|   40|    80|
    | yy|2020-01-11|   1|   20|    40|
    | yy|2020-01-12|   1|   20|    20|
    | yy|2020-01-05|   2|   40|   240|
    | yy|2020-01-06|   2|   40|   260|
    | yy|2020-01-07|   2|   40|   260|
    | yy|2020-01-08|   2|   40|   220|
    | yy|2020-01-09|   2|   40|   180|
    | yy|2020-01-10|   2|   40|   140|
    | yy|2020-01-11|   2|   60|   100|
    | yy|2020-01-12|   2|   40|    40|
    +---+----------+----+-----+------+
代码

所以我需要基于天列的求和值列,也就是说,若天列是5,我需要求和5行值


我加入了两个表,并使用窗口函数,我试图解决,但我没有解决,也无法想出如何解决它。你能告诉我如何解决这个问题吗?首先你可以在
x
上加入,然后在你的行上创建一个
行号()
,它将用于
在大于天的地方挑选出来(将它们变成
空值),然后
在仅分区的窗口上求和
在所有行上广播求和

更新

对于Spark2.4+,您可以在收集列表之后使用更高阶的函数
我假设数据按照所提供的示例进行排序,如果不是这样,则需要添加额外的步骤来确保

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

w=Window().partitionBy("x","flag")
w1=Window().partitionBy("x","flag").orderBy(F.to_date("date","yyyy-dd-MM"))

df.join(df1,['x'])\
  .withColumn("result", F.collect_list("value").over(w))\
  .withColumn("rowNum", F.row_number().over(w1)-1)\
  .withColumn("result", F.expr("""aggregate(transform(result,(x,i)->array(x,i)),0,(acc,x)-> \
                             IF((int(x[1])>=rowNum)and(int(x[1])<days+rowNum),int(x[0])+acc,acc))"""))\
  .drop("flag","rowNum","days").show()


#+---+----------+-----+------+
#|  x|      date|value|result|
#+---+----------+-----+------+
#| ll|2020-01-05|   10|    50|
#| ll|2020-01-06|   10|    50|
#| ll|2020-01-07|   10|    60|
#| ll|2020-01-08|   10|    60|
#| ll|2020-01-09|   10|    50|
#| ll|2020-01-10|   10|    40|
#| ll|2020-01-11|   20|    30|
#| ll|2020-01-12|   10|    10|
#| ll|2020-01-05|   30|   160|
#| ll|2020-01-06|   30|   140|
#| ll|2020-01-07|   30|   120|
#| ll|2020-01-08|   40|   100|
#| ll|2020-01-09|   30|    60|
#| ll|2020-01-10|   10|    30|
#| ll|2020-01-11|   10|    20|
#| ll|2020-01-12|   10|    10|
#| yy|2020-01-05|   20|   140|
#| yy|2020-01-06|   20|   140|
#| yy|2020-01-07|   20|   140|
#| yy|2020-01-08|   20|   120|
#| yy|2020-01-09|   20|   100|
#| yy|2020-01-10|   40|    80|
#| yy|2020-01-11|   20|    40|
#| yy|2020-01-12|   20|    20|
#| yy|2020-01-05|   40|   240|
#| yy|2020-01-06|   40|   260|
#| yy|2020-01-07|   40|   260|
#| yy|2020-01-08|   40|   220|
#| yy|2020-01-09|   40|   180|
#| yy|2020-01-10|   40|   140|
#| yy|2020-01-11|   60|   100|
#| yy|2020-01-12|   40|    40|
#+---+----------+-----+------+
从pyspark.sql导入函数为F
从pyspark.sql.window导入窗口
w=Window().partitionBy(“x”,“标志”)
w1=窗口().分区依据(“x”,“标志”).订购依据(截止日期(“日期”,“yyyy-dd-MM”))
join(df1,['x'])\
.带列(“结果”,F.收集列表(“值”)。超过(w))\
.withColumn(“rowNum”,F.行编号()。在(w1)-1上方)\
.withColumn(“结果”,F.expr(“聚合”(转换(结果,(x,i)->数组(x,i)),0,(acc,x)->\

如果((int(x[1])>=rowNum)和(int(x[1]))如果我只有4行,但我的天数是5,那么一个查询,假设是标志1。因此,如果天数满足,我需要求和,如果天数不满足,我需要求和标志中的总行数。修改了预期结果新的结果列对我来说没有意义。前两行是50,后两行是60,然后它会逐渐减少。可以吗你要详细说明@Mohammad Murtaza Hashmi的公式,假设你在flag1部分有6天,你的天数是5天。第一行加起来是5行,第二行加起来是剩下的5行,但当你到第三行时,你只有4行,所以我们必须加起来是4行。因此,理想情况下,每行需要5个日期如果没有5行,则取所有可用行的值。我希望是这样helpful@Anji乐意帮忙,请接受答案关闭线程
from pyspark.sql import functions as F
from pyspark.sql.window import Window

w=Window().partitionBy("x","flag").orderBy(F.to_date("date","yyyy-dd-MM"))
w1=Window().partitionBy("x","flag")
df.join(df1, ['x'])\
  .withColumn("rowNum", F.row_number().over(w))\
  .withColumn("expected_result", F.sum(F.when(F.col("rowNum")>F.col("days")\
                                     ,F.lit(None)).otherwise(F.col("value")))\
                                      .over(w1)).drop("days","rowNum").show()

#+---+----------+----+-----+---------------+
#|  x|      date|flag|value|expected_result|
#+---+----------+----+-----+---------------+
#| ll|2020-01-05|   1|   10|           50.0|
#| ll|2020-01-06|   1|   10|           50.0|
#| ll|2020-01-07|   1|   10|           50.0|
#| ll|2020-01-08|   1|   10|           50.0|
#| ll|2020-01-09|   1|   10|           50.0|
#| ll|2020-01-10|   1|   10|           50.0|
#| ll|2020-01-11|   1|   10|           50.0|
#| ll|2020-01-12|   1|   10|           50.0|
#| ll|2020-01-05|   2|   30|          150.0|
#| ll|2020-01-06|   2|   30|          150.0|
#| ll|2020-01-07|   2|   30|          150.0|
#| ll|2020-01-08|   2|   30|          150.0|
#| ll|2020-01-09|   2|   30|          150.0|
#| ll|2020-01-10|   2|   10|          150.0|
#| ll|2020-01-11|   2|   10|          150.0|
#| ll|2020-01-12|   2|   10|          150.0|
#| yy|2020-01-05|   1|   20|          120.0|
#| yy|2020-01-06|   1|   20|          120.0|
#| yy|2020-01-07|   1|   20|          120.0|
#| yy|2020-01-08|   1|   20|          120.0|
#+---+----------+----+-----+---------------+
#only showing top 20 rows
from pyspark.sql import functions as F
from pyspark.sql.window import Window

w=Window().partitionBy("x","flag")
w1=Window().partitionBy("x","flag").orderBy(F.to_date("date","yyyy-dd-MM"))

df.join(df1,['x'])\
  .withColumn("result", F.collect_list("value").over(w))\
  .withColumn("rowNum", F.row_number().over(w1)-1)\
  .withColumn("result", F.expr("""aggregate(transform(result,(x,i)->array(x,i)),0,(acc,x)-> \
                             IF((int(x[1])>=rowNum)and(int(x[1])<days+rowNum),int(x[0])+acc,acc))"""))\
  .drop("flag","rowNum","days").show()


#+---+----------+-----+------+
#|  x|      date|value|result|
#+---+----------+-----+------+
#| ll|2020-01-05|   10|    50|
#| ll|2020-01-06|   10|    50|
#| ll|2020-01-07|   10|    60|
#| ll|2020-01-08|   10|    60|
#| ll|2020-01-09|   10|    50|
#| ll|2020-01-10|   10|    40|
#| ll|2020-01-11|   20|    30|
#| ll|2020-01-12|   10|    10|
#| ll|2020-01-05|   30|   160|
#| ll|2020-01-06|   30|   140|
#| ll|2020-01-07|   30|   120|
#| ll|2020-01-08|   40|   100|
#| ll|2020-01-09|   30|    60|
#| ll|2020-01-10|   10|    30|
#| ll|2020-01-11|   10|    20|
#| ll|2020-01-12|   10|    10|
#| yy|2020-01-05|   20|   140|
#| yy|2020-01-06|   20|   140|
#| yy|2020-01-07|   20|   140|
#| yy|2020-01-08|   20|   120|
#| yy|2020-01-09|   20|   100|
#| yy|2020-01-10|   40|    80|
#| yy|2020-01-11|   20|    40|
#| yy|2020-01-12|   20|    20|
#| yy|2020-01-05|   40|   240|
#| yy|2020-01-06|   40|   260|
#| yy|2020-01-07|   40|   260|
#| yy|2020-01-08|   40|   220|
#| yy|2020-01-09|   40|   180|
#| yy|2020-01-10|   40|   140|
#| yy|2020-01-11|   60|   100|
#| yy|2020-01-12|   40|    40|
#+---+----------+-----+------+