如何在pyspark和sql的一个数据框中应用多个条件并附加到同一个表
Posted
技术标签:
【中文标题】如何在pyspark和sql的一个数据框中应用多个条件并附加到同一个表【英文标题】:how to apply multiple conditions and append to the same table in one dataframe in pyspark and sql 【发布时间】:2020-05-14 14:03:12 【问题描述】:我正在尝试通过每周减少来执行此循环。如果 id 和 class_gp 组合已在前一周出现,则这些组合将在当前周/未来周删除。
数据框是这样的
df1:
ID Week_ID class_gp school_nm
1 20200101 A 101
1 20200101 B 101
1 20200107 A 101
1 20200107 B 101
1 20200107 C 101
1 20200114 B 101
1 20200114 D 101
1 20200121 B 101
1 20200121 D 101
1 20200121 E 101
理想的输出应该是这样的:
ID Week_ID class_gp school_nm
1 20200101 A 101
1 20200101 B 101
1 20200107 C 101
1 20200114 D 101
1 20200121 E 101
我不太擅长 for 循环,所以我使用了最愚蠢的方法,每周创建数据框,然后将它们全部加入。
删除第 1 周的 id 和 class_gp 组合以用于剩余的几周
t1 = df1.where("week_id = '20200101'")
df2 = df1.join(t1,
[df1.id == t1.id,df1.class_gp == t1.class_gp],
how='left_anti')
在剩下的几周内删除第 2 周的 id 和 class_gp 组合
t2 = df2.where("week_id= '20200107'")
df3 = df2.join(t2,
[df2.id == t2.id,df2.class_gp == t2.class_gp],
how='left_anti'
)....
并像这样创建所有 18 周。
但是创建如此多的数据框并以这样的方式运行会使其非常慢。
我想知道是否有一种简单的方法可以创建一个看起来像理想输出的单个数据框。
【问题讨论】:
【参考方案1】:你可以使用窗口函数来实现它:
val windowSpec=Window.partitionBy("class","school").orderBy("week")
然后将 row_number 函数应用于窗口并选择 row=1 的行,如下所示
scala> school.withColumn("row", row_number().over(windowSpec)).where("row=1").orderBy("week","class").drop("row").show(false)
+---+--------+-----+------+
|id |week |class|school|
+---+--------+-----+------+
|1 |20200101|A |101 |
|1 |20200101|B |101 |
|1 |20200107|C |101 |
|1 |20200114|D |101 |
|1 |20200121|E |101 |
+---+--------+-----+------+
【讨论】:
我使用 .partitionBy("class","ID") 和行号。有用!谢谢。【参考方案2】:您只需要 2 行 Python 代码
df=df.sort_values(by=['Week_ID'], ascending=True)
df=df.drop_duplicates(subset=['ID','class_gp'], keep='first')
【讨论】:
以上是关于如何在pyspark和sql的一个数据框中应用多个条件并附加到同一个表的主要内容,如果未能解决你的问题,请参考以下文章
如何对 Pyspark spark.sql 数据框中的数据进行同质化
如何在 pySpark 中有效地从字符串数据框中替换多个正则表达式模式的所有实例?