前一天pyspark的平均值列

时间:2019-02-11 12:07:43

标签: python apache-spark dataframe pyspark apache-spark-sql

我想创建一个新列,该列是使用pyspark的前一天销售额的平均值。

考虑这些值在不同的时间戳记。

例如,将其转换为:

| Date       | value |
|------------|-------|
| 2019/02/11 | 30    |
| 2019/02/11 | 40    |
| 2019/02/11 | 20    |
| 2019/02/12 | 10    |
| 2019/02/12 | 15    |

对此

| Date       | value | avg  |
|------------|-------|------|
| 2019/02/11 | 30    | null |
| 2019/02/11 | 40    | null |
| 2019/02/11 | 20    | null |
| 2019/02/12 | 10    | 30   |
| 2019/02/12 | 15    | 30   | 

我的想法:

使用过滤器和聚合函数获得平均值,但其抛出错误。不确定我在哪里做错了。

df = df.withColumn("avg",lit((df.filter(df["date"] == date_sub("date",1)).agg({"value": "avg"}))))

2 个答案:

答案 0 :(得分:1)

您可以使用Windows函数来执行此操作,但是必须创建一个新列来处理日期。 我向您的示例添加了几行:

df.withColumn(
  "rnk",
  F.dense_rank().over(Window.partitionBy().orderBy("date"))
).withColumn(
  "avg",
  F.avg("value").over(Window.partitionBy().orderBy("rnk").rangeBetween(-1,-1))
).show()

+----------+-----+---+----+
|      date|value|rnk| avg|
+----------+-----+---+----+
|2018-01-01|   20|  1|null|
|2018-01-01|   30|  1|null|
|2018-01-01|   40|  1|null|
|2018-01-02|   40|  2|30.0|
|2018-01-02|   30|  2|30.0|
|2018-01-03|   40|  3|35.0|
|2018-01-03|   40|  3|35.0|
+----------+-----+---+----+

您也可以使用聚合来实现:

agg_df = df.withColumn("date", F.date_add("date", 1)).groupBy('date').avg("value")
df.join(agg_df, how="full_outer", on="date").orderBy("date").show()

+----------+-----+----------+
|      date|value|avg(value)|
+----------+-----+----------+
|2018-01-01|   20|      null|
|2018-01-01|   30|      null|
|2018-01-01|   40|      null|
|2018-01-02|   30|      30.0|
|2018-01-02|   40|      30.0|
|2018-01-03|   40|      35.0|
|2018-01-03|   40|      35.0|
|2018-01-04| null|      40.0|
+----------+-----+----------+

答案 1 :(得分:0)

步骤0:创建数据框

from pyspark.sql.window import Window
from pyspark.sql.functions import col, avg, lag
df = sqlContext.createDataFrame([('2019/02/11',30),('2019/02/11',40),('2019/02/11',20),
                                 ('2019/02/12',10),('2019/02/12',15),
                                 ('2019/02/13',10),('2019/02/13',20)],['Date','value']) 

步骤1:首先计算平均值,然后使用windows函数获得1天的滞后时间。

my_window = Window.partitionBy().orderBy('Date')
df_avg_previous = df.groupBy('Date').agg(avg(col('value')).alias('avg'))
df_avg_previous = df_avg_previous.withColumn('avg', lag(col('avg'),1).over(my_window))
df_avg_previous.show()
+----------+----+
|      Date| avg|
+----------+----+
|2019/02/11|null|
|2019/02/12|30.0|
|2019/02/13|12.5|
+----------+----+

步骤2:最后,通过使用left联接来联接两个数据框。

df = df.join(df_avg_previous, ['Date'],how='left').orderBy('Date')
df.show()
+----------+-----+----+
|      Date|value| avg|
+----------+-----+----+
|2019/02/11|   40|null|
|2019/02/11|   20|null|
|2019/02/11|   30|null|
|2019/02/12|   10|30.0|
|2019/02/12|   15|30.0|
|2019/02/13|   10|12.5|
|2019/02/13|   20|12.5|
+----------+-----+----+