使用pyspark基于另一列中的值连接两列

使用pyspark基于另一列中的值连接两列,pyspark,apache-spark-sql,pyspark-sql,Pyspark,Apache Spark Sql,Pyspark Sql,我在一个数据帧中的一列中有一个值列表,我想用它来过滤另一个较大的数据帧,该数据帧有两列可供匹配 这里有一个例子 df1=sqlContext.createDataFrame( [(1,“a”),(2,“b”),(3,“c”),(4,“d”),(5,“e”)], (“ID”、“标签1”)) df2=sqlContext.createDataFrame( [ (1,2,“x”), (2,1,“y”), (3,1,“z”), (4,6,“s”), (7,2,“t”), (8,9,“z”) ], (“I

我在一个数据帧中的一列中有一个值列表,我想用它来过滤另一个较大的数据帧,该数据帧有两列可供匹配

这里有一个例子

df1=sqlContext.createDataFrame(
[(1,“a”),(2,“b”),(3,“c”),(4,“d”),(5,“e”)],
(“ID”、“标签1”))
df2=sqlContext.createDataFrame(
[
(1,2,“x”),
(2,1,“y”),
(3,1,“z”),
(4,6,“s”),
(7,2,“t”),
(8,9,“z”)
],
(“ID1”、“ID2”、“label2”)
)
最后我想得到的是一个数据帧,它包含来自
df2
的条目,其中
ID1
ID2
都位于
df1
中。在这个例子中,这看起来像这样

+---+---+------+
|ID1 | ID2 |标签|
+---+---+------+
|1 | 2 | x|
|2 | 1 | y|
|3 | 1 | z|
+---+---+------+
我已经尝试过通过如下连接来实现这一点:

df=df1.join(df2,(df1.ID==df2.ID1)|(df1.ID==df2.ID2))
但这炸毁了我的桌子,给了我

+---+------+---+---+------+
|ID | label1 | ID1 | ID2 | label2|
+---+------+---+---+------+
|1 | a | 1 | 2 | x|
|1 | a | 2 | 1 | y|
|1 | a | 3 | 1 | z|
|2 | b | 1 | 2 | x|
|2 | b | 2 | 1 | y|
|2 | b | 7 | 2 | t|
|3 | c | 3 | 1 | z|
|4 | d | 4 | 6 | s|
+---+------+---+---+------+
那么

df=df1.join(df2,(df1.ID==df2.ID1)和(df1.ID==df2.ID2))

显然也不是我想要的。。。。。。。。有任何帮助吗?

我认为您可以使用初始的join语句对数据帧进行进一步分组,并选择出现两次的行,因为
ID1
ID2
应该出现在
df1
中。因此,它们应该在结果中出现两次,因为联接应该使用
df1
中的两个ID值复制
df2
的行

结果语句如下所示:

从pyspark.sql.functions导入col
df2.join(
df1,
[(df1.ID==df2.ID1)|(df1.ID==df2.ID2)],
how=“left”
).groupBy(“ID1”、“ID2”、“label”).count().filter(col(“count”)==2.show()
结果是:

+---+---+-----+-----+
|ID1 | ID2 |标签|计数|
+---+---+-----+-----+ 
|2 | 1 | y | 2 |
|3 | 1 | z | 2 |
|1 | 2 | x | 2|
+---+---+-----+-----+

如果您不喜欢count列,您可以在语句中附加一个
select(“ID1”、“ID2”、“label”)
,我认为您可以使用初始的join语句对数据帧进行进一步分组,并选择出现两次的行,因为
ID1
ID2
应该出现在
df1
中。因此,它们应该在结果中出现两次,因为联接应该使用
df1
中的两个ID值复制
df2
的行

结果语句如下所示:

从pyspark.sql.functions导入col
df2.join(
df1,
[(df1.ID==df2.ID1)|(df1.ID==df2.ID2)],
how=“left”
).groupBy(“ID1”、“ID2”、“label”).count().filter(col(“count”)==2.show()
结果是:

+---+---+-----+-----+
|ID1 | ID2 |标签|计数|
+---+---+-----+-----+ 
|2 | 1 | y | 2 |
|3 | 1 | z | 2 |
|1 | 2 | x | 2|
+---+---+-----+-----+

如果您不喜欢计数列,可以在语句中附加一个
select(“ID1”、“ID2”、“label”)
,这是使用spark sql的另一种方法:

首先将数据帧注册为表:

df1.createOrReplaceTempView('df1'))
df2.createOrReplaceTempView('df2')
接下来运行以下查询:

df=sqlContext.sql(
“从df2中选择*,其中ID1在(从df1中选择ID)和ID2在(从df1中选择ID)”
)
df.show()
#+---+---+------+
#|ID1 | ID2 |标签2|
#+---+---+------+
#|3 | 1 | z|
#|2 | 1 | y|
#|1 | 2 | x|
#+---+---+------+

这是使用spark sql的另一种方法:

首先将数据帧注册为表:

df1.createOrReplaceTempView('df1'))
df2.createOrReplaceTempView('df2')
接下来运行以下查询:

df=sqlContext.sql(
“从df2中选择*,其中ID1在(从df1中选择ID)和ID2在(从df1中选择ID)”
)
df.show()
#+---+---+------+
#|ID1 | ID2 |标签2|
#+---+---+------+
#|3 | 1 | z|
#|2 | 1 | y|
#|1 | 2 | x|
#+---+---+------+

您可以单独使用intersect after筛选数据。下面是使用core spark api的解决方案

>>> df1.show()
+---+------+
| ID|label1|
+---+------+
|  1|     a|
|  2|     b|
|  3|     c|
|  4|     d|
|  5|     e|
+---+------+

>>> df2.show()
+---+---+------+
|ID1|ID2|label2|
+---+---+------+
|  1|  2|     x|
|  2|  1|     y|
|  3|  1|     z|
|  4|  6|     s|
|  7|  2|     t|
|  8|  9|     z|
+---+---+------+

>>> df3 = df1.join(df2, (df1.ID == df2.ID1)).select(df2['*'])
>>> df4 = df1.join(df2, (df1.ID == df2.ID2)).select(df2['*'])
>>> df3.intersect(df4).show()
+---+---+------+                                                                
|ID1|ID2|label2|
+---+---+------+
|  2|  1|     y|
|  3|  1|     z|
|  1|  2|     x|
+---+---+------+

可以单独使用intersect after筛选数据。下面是使用core spark api的解决方案

>>> df1.show()
+---+------+
| ID|label1|
+---+------+
|  1|     a|
|  2|     b|
|  3|     c|
|  4|     d|
|  5|     e|
+---+------+

>>> df2.show()
+---+---+------+
|ID1|ID2|label2|
+---+---+------+
|  1|  2|     x|
|  2|  1|     y|
|  3|  1|     z|
|  4|  6|     s|
|  7|  2|     t|
|  8|  9|     z|
+---+---+------+

>>> df3 = df1.join(df2, (df1.ID == df2.ID1)).select(df2['*'])
>>> df4 = df1.join(df2, (df1.ID == df2.ID2)).select(df2['*'])
>>> df3.intersect(df4).show()
+---+---+------+                                                                
|ID1|ID2|label2|
+---+---+------+
|  2|  1|     y|
|  3|  1|     z|
|  1|  2|     x|
+---+---+------+

创建
df1
时会出现错误,因为您无法使用该语法创建包含一个元素的元组。您应该将
[(1,),(2,),(3,),(4,),(5,)],(“ID”,)
(请注意内部逗号!)放在下面,谢谢!我现在已经编辑了我的问题。
df1
的创建会产生错误,因为不能使用该语法创建包含一个元素的元组。您应该将
[(1,),(2,),(3,),(4,),(5,)],(“ID”,)
(请注意内部逗号!)放在下面,谢谢!我现在编辑了我的问题。这是有道理的。谢谢唯一的问题是我得到了一个错误,声明'NameError:name'col'未定义'这是来自
pyspark.sql.functions
的函数,但多亏@pault,他已经编辑了我的答案,这才有意义。谢谢唯一的问题是,我在声明“NameError:name'col'未定义”时出错。这是来自
pyspark.sql.functions
的函数,但多亏@pault,他已经编辑了我的答案