![](/img/trans.png)
[英]How to use milliseconds as an argument in PySpark window(). rangebetween function?
[英]How to use pyspark dataframe window function
我有一个如下所示的数据框
我想获得一个数据框,它具有最新版本和最新日期。第一个过滤条件将是最新版本,然后是最新日期结果数据框应如下所示
我正在使用窗口函数来实现这一点。我写了下面的一段代码。
wind = Window.partitionBy("id")
data = data.withColumn("maxVersion", F.max("version").over(wind)) \
.withColumn("maxDt", F.max("dt").over(wind)) \
.where(F.col("version") == F.col("maxVersion")) \
.where(F.col("maxDt") == F.col("dt")) \
.drop(F.col("maxVersion")) \
.drop(F.col("maxDt"))
我不确定我错过了什么。我只得到一个 ID 为 100 的输出。请帮我解决这个问题
正如您所提到的,您的操作中有一个顺序:第一个版本,然后是 dt 基本上,您只需要选择最大版本(删除其他所有内容),然后选择最大 dt 并删除其他所有内容。 你只需要像这样切换 2 行:
wind = Window.partitionBy("id")
data = data.withColumn("maxVersion", F.max("version").over(wind)) \
.where(F.col("version") == F.col("maxVersion")) \
.withColumn("maxDt", F.max("dt").over(wind)) \
.where(F.col("maxDt") == F.col("dt")) \
.drop(F.col("maxVersion")) \
.drop(F.col("maxDt"))
id 100 只有一行的原因是因为在这种情况下最大版本和最大 dt 发生在同一行(你很幸运)。 但对于 id 200 则不是这样。
基本上,您的配方存在几个问题。 首先,您需要将日期从字符串更改为正确的日期格式。 然后 pyspark 中的 Window 允许您一个接一个地指定列的顺序。 然后是rank()
函数,它允许您在 Window 上对结果进行排名。 最后剩下的就是选择第一个等级。
from pyspark.sql.types import *
from pyspark import SparkContext, SQLContext
import pyspark.sql.functions as F
from pyspark.sql import Window
sc = SparkContext('local')
sqlContext = SQLContext(sc)
data1 = [
(100,1,"2020-03-19","Nil1"),
(100,2,"2020-04-19","Nil2"),
(100,2,"2020-04-19","Nil2"),
(100,2,"2020-05-19","Ni13"),
(200,1,"2020-09-19","Jay1"),
(200,2,"2020-07-19","Jay2"),
(200,2,"2020-08-19","Jay3"),
]
df1Columns = ["id", "version", "dt", "Name"]
df1 = sqlContext.createDataFrame(data=data1, schema = df1Columns)
df1 = df1.withColumn("dt",F.to_date(F.to_timestamp("dt", 'yyyy-MM-dd')).alias('dt'))
print("Schema.")
df1.printSchema()
print("Actual initial data")
df1.show(truncate=False)
wind = Window.partitionBy("id").orderBy(F.desc("version"), F.desc("dt"))
df1 = df1.withColumn("rank", F.rank().over(wind))
print("Ranking over the window spec specified")
df1.show(truncate=False)
final_df = df1.filter(F.col("rank") == 1).drop("rank")
print("Filtering the final result by applying the rank == 1 condition")
final_df.show(truncate=False)
输出 :
Schema.
root
|-- id: long (nullable = true)
|-- version: long (nullable = true)
|-- dt: date (nullable = true)
|-- Name: string (nullable = true)
Actual initial data
+---+-------+----------+----+
|id |version|dt |Name|
+---+-------+----------+----+
|100|1 |2020-03-19|Nil1|
|100|2 |2020-04-19|Nil2|
|100|2 |2020-04-19|Nil2|
|100|2 |2020-05-19|Ni13|
|200|1 |2020-09-19|Jay1|
|200|2 |2020-07-19|Jay2|
|200|2 |2020-08-19|Jay3|
+---+-------+----------+----+
Ranking over the window spec specified
+---+-------+----------+----+----+
|id |version|dt |Name|rank|
+---+-------+----------+----+----+
|100|2 |2020-05-19|Ni13|1 |
|100|2 |2020-04-19|Nil2|2 |
|100|2 |2020-04-19|Nil2|2 |
|100|1 |2020-03-19|Nil1|4 |
|200|2 |2020-08-19|Jay3|1 |
|200|2 |2020-07-19|Jay2|2 |
|200|1 |2020-09-19|Jay1|3 |
+---+-------+----------+----+----+
Filtering the final result by applying the rank == 1 condition
+---+-------+----------+----+
|id |version|dt |Name|
+---+-------+----------+----+
|100|2 |2020-05-19|Ni13|
|200|2 |2020-08-19|Jay3|
+---+-------+----------+----+
一种更简洁的方法可能是执行以下操作:
w = Window.partitionBy("id").orderBy(F.col('version').desc(), F.col('dt').desc())
df1.withColumn('maximum', F.row_number().over(w)).filter('maximum = 1').drop('maximum').show()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.