根据DataFrame连接编写列

时间:2018-06-03 17:20:52

标签: apache-spark dataframe pyspark

我们说我有两个数据框架 - df1df2 - 两者都有foobar列。列foo是CRC32哈希值,如123456,列bar是布尔字段,默认为False

在pyspark中,比较foo在两个数据框架中的值的有效方法是,如果不是<<},则将列bar写入True / strong>匹配。

例如,给定以下两个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

非常感谢任何指导。

更新7/1/2018

成功使用已接受的答案已经有一段时间了,遇到一种情况会使解决方案不太合适。如果其中一个联接的DataFrame中的多个行与foo的值相同,而是来自联接中其他DataFrame的行,则会导致该共享值上的行的笛卡尔积增长。

在我的情况下,我有基于空字符串的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的任何建议,将不胜感激。

另一个更新7/1/2018,替代答案

如果没有id列加入,我就会使问题复杂化。使用它时,根据transformed列的直接比较,加入和编写fingerprint列相对简单:

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)

2 个答案:

答案 0 :(得分:2)

使用df2 df1的{​​em>别名左连接并使用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|
+------+-----+

答案 1 :(得分:0)

我建议使用左连接并编写代码,以便当数据为null时输出false,反之亦然。