我有一个PySpark数据帧(例如df
),如下所示:
+-----+-----+----------+-----+
| name| type| timestamp|score|
+-----+-----+----------+-----+
|name1|type1|2012-01-10| 11|
|name1|type1|2012-01-11| 14|
|name1|type1|2012-01-12| 2|
|name1|type3|2012-01-12| 3|
|name1|type3|2012-01-11| 55|
|name1|type1|2012-01-13| 10|
|name1|type2|2012-01-14| 11|
|name1|type2|2012-01-15| 14|
|name2|type2|2012-01-10| 2|
|name2|type2|2012-01-11| 3|
|name2|type2|2012-01-12| 55|
|name2|type1|2012-01-10| 10|
|name2|type1|2012-01-13| 55|
|name2|type1|2012-01-14| 10|
+-----+-----+----------+-----+
在上面的数据框中,对于每个name
,我想计算3个连续时间戳中有多少score
个值。例如,对于name1
,我希望能够检测到score
至2012-01-10
之间有5个2012-01-12
值,而{{1}之间有3个分数}到2012-01-13
(对于2012-01-15
依此类推)。
在我的输出数据框中,我希望行数少于name2
中的行数。具体来说,由于我正在对size = 3的窗口进行汇总/计数,因此我希望行数约为〜1/3。我仍然希望有一个timestamp列,它代表窗口的第一个条目。我希望窗户不重叠。
如何使用PySpark做到这一点?
这是我到目前为止尝试过的:
df
但是,当我使用上述技术时,出现以下错误。
win = W.orderBy("timestamp").partitionBy("name").rowsBetween(0,3)
df_agg = df.groupBy( "timestamp" , F.col("name") ).agg( F.count( F.col("score") ).over(win) )
您可以使用以下代码段创建 org.apache.spark.sql.AnalysisException: expression '`score`' is neither present in the group by, nor is it an aggregate function.
(示例数据框)。
df
答案 0 :(得分:0)
我尝试了以下操作,告诉我这是否是预期的输出:
from pyspark.sql.window import Window
w = Window.partitionBy("name").orderBy("timestamp").rowsBetween(0, 3)
df_agg = demo_df.withColumn("group_count", F.count("score").over(w))
df_agg.show()
# +-----+-----+----------+-----+-----------+
# | name| type| timestamp|score|group_count|
# +-----+-----+----------+-----+-----------+
# |name1|type1|2012-01-10| 11| 4|
# |name1|type1|2012-01-11| 14| 4|
# |name1|type3|2012-01-11| 55| 4|
# |name1|type1|2012-01-12| 2| 4|
# |name1|type3|2012-01-12| 3| 4|
# |name1|type1|2012-01-13| 10| 3|
# |name1|type2|2012-01-14| 11| 2|
# |name1|type2|2012-01-15| 14| 1|
# |name2|type2|2012-01-10| 2| 4|
# |name2|type1|2012-01-10| 10| 4|
# |name2|type2|2012-01-11| 3| 4|
# |name2|type2|2012-01-12| 55| 3|
# |name2|type1|2012-01-13| 55| 2|
# |name2|type1|2012-01-14| 10| 1|
# +-----+-----+----------+-----+-----------+
partitionBy
等效于groupBy
功能的Window
,至少在功能上是明智的。
答案 1 :(得分:0)
一个选项是创建一个数据框,其日期范围从数据框的较低日期开始(可能是2012-01-10)。使用此新数据框对数据框进行内部联接,以获取具有所需日期范围的当前数据,现在您可以使用名称,类型和时间戳进行分组,并使用总和进行汇总。我认为这是最好的选择。您创建的数据框包含日期范围,因此不会花费太多时间。