【发布时间】:2019-12-26 15:13:17
【问题描述】:
考虑以下包含商店和书籍的数据框:
+-----------+------+-------+
| storename | book | price |
+-----------+------+-------+
| S1 | B11 | 10$ | <<
| S2 | B11 | 11$ |
| S1 | B15 | 29$ | <<
| S2 | B10 | 25$ |
| S2 | B16 | 30$ |
| S1 | B09 | 21$ | <
| S3 | B15 | 22$ |
+-----------+------+-------+
假设我们需要找到有两本书的商店,即B11 和B15。在这里,答案是S1,因为它存储了两本书。
一种方法是使用以下命令找到拥有书籍B11 的商店与拥有书籍B15 的商店的交集:
val df_select = df.filter($"book" === "B11").select("storename")
.join(df.filter($"book" === "B15").select("storename"), Seq("storename"), "inner")
其中包含两者的商店名称。
但我想要一张桌子
+-----------+------+-------+
| storename | book | price |
+-----------+------+-------+
| S1 | B11 | 10$ | <<
| S1 | B15 | 29$ | <<
| S1 | B09 | 21$ | <
+-----------+------+-------+
其中包含与该履行商店相关的所有记录。请注意,B09 不会被忽略。 (用例:用户可以在 same 商店中浏览一些 other 书籍)
我们可以通过将上述结果与原始数据框进行另一个交集来做到这一点:
df_select.join(df, Seq("storename"), "inner")
但是,我看到step 1 的可扩展性和可读性问题,因为如果书籍数量超过 2,我必须继续将一个数据帧连接到另一个数据帧。要做的事情很多,那就是也容易出错。有没有更优雅的方式来做同样的事情?比如:
val storewise = Window.partitionBy("storename")
df.filter($"book".contains{"B11", "B15"}.over(storewise))
【问题讨论】:
-
S2 两本书都有,为什么会被过滤掉?如果您使用 spark 2.4+,则尝试执行 array_except 并按结果数组的大小进行过滤。
-
啊……我打错了。现在更正..
-
spark 2.4+能用吗?
-
Spark 版本为 2.4.0
-
感谢@vdep 和@jxc。添加两个概念,即你们建议的
collect_set和array_except,我能够解决这个问题。 :)
标签: scala dataframe apache-spark filter