scala 根据具有相同值的 2 列过滤掉连接 df 中的行 - 最佳方式

Posted

技术标签:

【中文标题】scala 根据具有相同值的 2 列过滤掉连接 df 中的行 - 最佳方式【英文标题】:scala filtering out rows in a joined df based on 2 columns with same values - best way 【发布时间】:2019-01-06 19:29:16 【问题描述】:

我正在比较 2 个数据帧。 我选择逐列比较它们

我从父数据框创建了 2 个较小的数据框。 基于连接列和比较列:

Created 1st dataframe:
val df1_subset = df1.select(subset_cols.head, subset_cols.tail: _*)

+----------+---------+-------------+
|first_name|last_name|loyalty_score|
+----------+---------+-------------+
|      tom |   cruise|           66|
|    blake |   lively|           66|
|       eva|    green|           44|
|      brad|     pitt|           99|
|     jason|    momoa|           34|
|   george |  clooney|           67|
|        ed|  sheeran|           88|
|    lionel|    messi|           88|
|      ryan| reynolds|           45|
|     will |    smith|           67|
|      null|     null|             |
+----------+---------+-------------+

Created 2nd Dataframe:
val df1_1_subset = df1_1.select(subset_cols.head, subset_cols.tail: _*)

+----------+---------+-------------+
|first_name|last_name|loyalty_score|
+----------+---------+-------------+
|      tom |   cruise|           34|
|      brad|     pitt|           78|
|       eva|    green|           56|
|      tom |   cruise|           99|
|     jason|    momoa|           34|
|   george |  clooney|           67|
|   george |  clooney|           88|
|    lionel|    messi|           88|
|      ryan| reynolds|           45|
|     will |    smith|           67|
|      kyle|   jenner|           56|
|    celena|    gomez|            2|
+----------+---------+-------------+

然后我加入了 2 个子集 我将这些作为完全外部连接加入以获得以下结果:

val df_subset_joined = df1_subset.join(df1_1_subset, joinColsArray, "full_outer")

Joined Subset
+----------+---------+-------------+-------------+
|first_name|last_name|loyalty_score|loyalty_score|
+----------+---------+-------------+-------------+
|     will |    smith|           67|           67|
|   george |  clooney|           67|           67|
|   george |  clooney|           67|           88|
|    blake |   lively|           66|         null|
|    celena|    gomez|         null|            2|
|       eva|    green|           44|           56|
|      null|     null|             |         null|
|     jason|    momoa|           34|           34|
|        ed|  sheeran|           88|         null|
|    lionel|    messi|           88|           88|
|      kyle|   jenner|         null|           56|
|      tom |   cruise|           66|           34|
|      tom |   cruise|           66|           99|
|      brad|     pitt|           99|           78|
|      ryan| reynolds|           45|           45|
+----------+---------+-------------+-------------+

然后我尝试使用列位置过滤掉两个比较列中相同的元素(本例中为loyalty_scores)

df_subset_joined.filter(_c2 != _c3).show

但这没有用。我收到以下错误:

Error:(174, 33) not found: value _c2
df_subset_joined.filter(_c2 != _c3).show

对我来说,获得连接数据框的最有效方法是什么,我只能看到比较列中不匹配的行。

我想保持这种动态,所以硬编码列名不是一种选择。

感谢您帮助我理解这一点。

【问题讨论】:

【参考方案1】:

您需要使用别名并使我们成为空安全比较运算符 (https://spark.apache.org/docs/latest/api/sql/index.html#_9),另请参阅 https://***.com/a/54067477/1138523

val df_subset_joined = df1_subset.as("a").join(df1_1_subset.as("b"), joinColsArray, "full_outer")

df_subset_joined.filter(!($"a.loyality_score" <=> $"b.loyality_score")).show

编辑:对于动态列名,您可以使用字符串插值

import org.apache.spark.sql.functions.col
val xxx : String = ???

df_subset_joined.filter(!(col(s"a.$xxx") <=> col(s"b.$xxx"))).show

【讨论】:

谢谢。但我想避免列名的硬编码。这就是我的全部挑战。有没有办法使用:df_subset_joined.filter($"a.XXX" =!= $"b.XXX").show 其中XXX是一个动态值 这对我不起作用,但确实如此:val filter_str = (s"a.$col")+" != "+s"b.$col" df_subset_joined.filter(filter_str)。显示您的答案绝对是正确的方向。 @banditKing 可以尝试获取我的答案,我使用了错误的相等运算符

以上是关于scala 根据具有相同值的 2 列过滤掉连接 df 中的行 - 最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL - 过滤掉包含具有特定值的行的分区或行组

如何将具有相同列值的mysql行分组为一行?

如何在 s-s-rS 的任何列中过滤具有空值的行

连接具有相同值的行的列值(不同列的)

根据另一列的字段值选择具有相同列值的行

通过具有最大列值的记录过滤 Django 查询