簡體   English   中英

PySpark - 為列 Window 提取最大值 24 小時,然后刪除重復項

[英]PySpark - Extract Max Value for Column for 24 Hour Window, Then Drop Duplicates

我需要為每個id找到valuemax_value 只需要記錄一次最大值,並且在date當天的第一條記錄處

+---+-------------------+-----+----------+
| id|               date|value| date_only|
+---+-------------------+-----+----------+
| J1|2016-10-01 00:00:00| Null|2016-10-01| 
| J1|2016-10-01 01:00:00|    1|2016-10-01|
| J1|2016-10-01 12:30:30|    3|2016-10-01|
| J9|2016-10-06 00:00:00|    2|2016-10-06|
| J9|2016-10-06 09:20:00|    4|2016-10-06|
| J9|2016-10-06 09:20:00| Null|2016-10-06|
+---+-------------------+-----+----------+

所需 DataFrame:

+---+-------------------+-----+----------+---------+
| id|               date|value| date_only|max_value|
+---+-------------------+-----+----------+---------+
| J1|2016-10-01 00:00:00| Null|2016-10-01|        3|
| J1|2016-10-01 01:00:00|    1|2016-10-01|     Null|
| J1|2016-10-01 12:30:30|    3|2016-10-01|     Null|
| J9|2016-10-06 00:00:00|    2|2016-10-06|        4|
| J9|2016-10-06 09:20:00|    4|2016-10-06|     Null|
| J9|2016-10-06 09:20:00| Null|2016-10-06|     Null|
+---+-------------------+-----+----------+---------+

我嘗試了什么:

這只會保留 groupby 變量並從新數據框中排除所有其他變量(100s))

df = df.groupBy("id", "date_only").agg(max("max_value").alias("max_value1")).sort('date_only')

我在下面嘗試過的示例代碼。 每個日期有 96 行,但有時不匹配。 是否有另一個 function 像 pandas DateTime 或者我是否需要刪除 arg 之間的行?

w = Window.partitionBy("ID").orderBy(F.col("date_only").cast('long'))

main = main.withColumn('max_value', F.max("value").over(w))

我也嘗試過,但是它沒有更改列中的重復值:

df.groupBy("ID", "Date").agg(first("max_value").alias("max_value"), count("*").alias("cn")) \
  .withColumn("max_value", when(col("cn") > lit(1), lit(None)).otherwise(col("max_value")))

您可以將兩個 WinSpecs 與它們的默認框架一起使用(下面來自doc ):

注意 未定義排序時,默認使用無界 window 幀(rowFrame、unboundedPreceding、unboundedFollowing)。 定義排序時,默認使用增長的 window 框架(rangeFrame、unboundedPreceding、currentRow)。

from pyspark.sql import Window, functions as F
w1 = Window.partitionBy('id') 
w2 = Window.partitionBy('id', F.col('date').astype('date')).orderBy('date')
# set up the first records on each day regardless if or not the date is ending with `00:00:00`
df.withColumn('max_value', F.when(F.row_number().over(w2)==1, F.max('value').over(w1))).show()
+---+-------------------+-----+----------+---------+                            
| id|               date|value| date_only|max_value|
+---+-------------------+-----+----------+---------+
| J1|2016-10-01 00:00:00| null|2016-10-01|        3|
| J1|2016-10-01 01:00:00|    1|2016-10-01|     null|
| J1|2016-10-01 12:30:30|    3|2016-10-01|     null|
| J9|2016-10-06 00:00:00|    2|2016-10-06|        4|
| J9|2016-10-06 09:20:00|    4|2016-10-06|     null|
| J9|2016-10-06 09:20:00| null|2016-10-06|     null|
+---+-------------------+-----+----------+---------+

編輯:根據評論,將所有以00:00:00結尾的日期調整為 max_value:

df.withColumn('max_value', F.when(F.col('date') == F.date_trunc('day', 'date'), F.max('value').over(w1))).show()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM