基于DataFrame join写列
Posted
技术标签:
【中文标题】基于DataFrame join写列【英文标题】:Write column based on DataFrame join 【发布时间】:2018-06-03 17:20:52 【问题描述】:假设我有两个 DataFrame -- df1
和 df2
-- 都有 foo
和 bar
列。 foo
列是一个 CRC32 哈希值,如 123456
,bar
列是一个布尔字段,默认为 False
。
在 pyspark 中,比较两个 DataFrame 中 foo
的值的有效方法是什么,如果它们不匹配,则将列 bar
写入 True
。
例如,给定以下两个 DataFrame:
# df1
foo | bar
-------|------
123456 | False
444555 | False
666777 | False
888999 | False
# df2
foo | bar
-------|------
938894 | False
129803 | False
666777 | False
888999 | False
我想要一个如下所示的新 DataFrame,其中两个 True
列的哈希值发生了变化:
# df3
foo | bar
-------|------
938894 | True <---
129803 | True <---
666777 | False
888999 | False
任何指导将不胜感激。
2018 年 7 月 1 日更新
在成功使用接受的答案很长一段时间后,遇到了一种情况,使解决方案不太适合。如果连接中的一个 DataFrame 中的多行与连接中另一个 DataFrame 中的行具有相同的 foo
值,则会导致该共享值上的行的笛卡尔积增长。
在我的例子中,我有基于空字符串的 CRC32 哈希值,这导致哈希值 0
。我还应该补充一点,我确实有一个唯一的字符串来匹配上面的行,在 id
下(可能有过于简单的情况),也许 这是要加入的事情:
它会产生这样的情况:
# df1
id |foo | bar
-----|-------|------
abc |123456 | False
def |444555 | False
ghi |0 | False
jkl |0 | False
# df2
id |foo | bar
-----|-------|------
abc |123456 | False
def |999999 | False
ghi |666777 | False
jkl |0 | False
如果选择了答案,将会得到一个数据框,其中包含 更多 行:
# df3
id |foo | bar
-----|-------|------
abc |123456 | False
def |999999 | True <---
ghi |0 | False
jkl |0 | False
jkl |0 | False # extra row add through join
我将保留选择的答案,因为它是对最初提出的问题的一个很好的答案。但是,对于如何处理 foo
列可能匹配的 DataFrame 的任何建议,我们将不胜感激。
2018 年 7 月 1 日的另一个更新,替代答案
如果没有加入 id
列,我已经把问题复杂化了。使用它时,根据fingerprint
列的直接比较,加入和编写transformed
列相对简单:
df2.alias("df2").join(df1.alias("df1"), df1.id == df2.id, 'left')\
.select(f.col('df2.foo'), f.when(df1.fingerprint != df2.fingerprint, f.lit(True)).otherwise(f.col('df2.bar')).alias('bar'))\
.show(truncate=False)
【问题讨论】:
【参考方案1】:df2
与df1
的别名左连接 并使用when
函数来检查不匹配的逻辑应该会给你你想要的输出
df2.alias("df2").join(df1.alias("df1"), df1.foo == df2.foo, 'left')\
.select(f.col('df2.foo'), f.when(f.isnull(f.col('df1.foo')), f.lit(True)).otherwise(f.col('df2.bar')).alias('bar'))\
.show(truncate=False)
这应该给你
+------+-----+
|foo |bar |
+------+-----+
|129803|true |
|938894|true |
|888999|false|
|666777|false|
+------+-----+
【讨论】:
这就是生意!效果很好,非常感谢。选择带有when
/otherwise
语句的列,然后选择aliasing
作为bar
,这是理解我如何在其他上下文中使用它的关键。谢谢!【参考方案2】:
我建议使用左连接并编写代码,以便当数据为空时输出假,反之亦然。
【讨论】:
谢谢,我也有同样的想法,但无法想象语法。以上是关于基于DataFrame join写列的主要内容,如果未能解决你的问题,请参考以下文章
基于不同类型spark 1.6列的Spark join dataframe