[英]SQL/Pyspark query to compre each value in a group with an aggregation of the same group
假设我有一张这样的桌子
ID | 日期 | 价值 |
---|---|---|
1 | 01/04 | 7 |
1 | 01/03 | 2 |
1 | 01/02 | 10 |
1 | 01/01 | 4 |
2 | 01/04 | 7 |
2 | 01/03 | 7 |
2 | 01/02 | 8 |
2 | 01/01 | 5 |
我想要得到的是另一个表,它的记录数相同,并且对于每条记录都有一个额外的列,其中包含最后n
条记录的平均值,该记录具有相同的id
,其日期恰好在给定记录之前。 例如,如果n=2
,对于第二行, id=1
和date=01/03
我想获得具有相同id
并且只是两个日期的两行中的平均值的value
就在01/03
之前,即 (10+4)/2=7。 所以,对于这个特定的记录,我会:
ID | 日期 | 价值 | 平均最后 2 条记录同一组 |
---|---|---|---|
1 | 01/04 | 7 | 6 |
1 | 01/03 | 2 | 7 |
1 | 01/02 | 10 | 4 |
1 | 01/01 | 4 | 无效的 |
2 | 01/04 | 7 | 7.5 |
2 | 01/03 | 7 | 6.5 |
2 | 01/02 | 8 | 5 |
2 | 01/01 | 5 | 无效的 |
我的问题是如何在关系(SQL)逻辑中实现这一点(Pyspark 中的实现也会有很大帮助)。
提前致谢
您可以使用窗口函数、按id
分区和按date
排序。
from pyspark.sql import functions as F
from pyspark.sql import Window
df = spark.createDataFrame(
[(1, '01/04', 7),
(1, '01/03', 2),
(1, '01/02', 10),
(1, '01/01', 4),
(2, '01/04', 7),
(2, '01/03', 7),
(2, '01/02', 8),
(2, '01/01', 5)],
['id', 'date', 'value']
)
df.createOrReplaceTempView('sample_data')
w = Window().partitionBy('id').orderBy('date').rowsBetween(-2, -1)
df = df.withColumn('avg', F.avg('value').over(w))
df.orderBy(F.col('id').asc(), F.col('date').desc()).show()
+---+-----+-----+----+
| id| date|value| avg|
+---+-----+-----+----+
| 1|01/04| 7| 6.0|
| 1|01/03| 2| 7.0|
| 1|01/02| 10| 4.0|
| 1|01/01| 4|null|
| 2|01/04| 7| 7.5|
| 2|01/03| 7| 6.5|
| 2|01/02| 8| 5.0|
| 2|01/01| 5|null|
+---+-----+-----+----+
spark.sql(
'''
SELECT
id,
date,
value,
AVG(value) OVER (PARTITION BY id ORDER BY date ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING) AS avg
FROM sample_data
ORDER BY id, date DESC
''').show()
+---+-----+-----+----+
| id| date|value| avg|
+---+-----+-----+----+
| 1|01/04| 7| 6.0|
| 1|01/03| 2| 7.0|
| 1|01/02| 10| 4.0|
| 1|01/01| 4|null|
| 2|01/04| 7| 7.5|
| 2|01/03| 7| 6.5|
| 2|01/02| 8| 5.0|
| 2|01/01| 5|null|
+---+-----+-----+----+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.