使用Scala Spark连接两个数据框

时间:2020-02-11 20:28:32

标签: scala apache-spark apache-spark-sql

我有两个数据框:

  • 第一个数据帧DFNum具有48列和58500行。
  • 第二个数据帧DFString具有7列和58500行。

两个数据框的列都互不相同。 我的目标只是将两个数据帧合并为一个具有55列(48 + 7)且始终为58500行的数据帧,以保持连接前的顺序。

我做了几次尝试,也阅读了其他问题,但没有成功。我特别尝试过:

val df = DFNum.join(DFString),这给了我以下错误: Detected implicit cartesian product for INNER join between logical plans. Join condition is missing or trivial. Join condition is missing or trivial. Either: use the CROSS JOIN syntax to allow cartesian products between these relations, or: enable implicit cartesian products by setting the configuration variable spark.sql.crossJoin.enabled=true;

显然,通过交叉连接,我得到的行比我想要的多得多:58500 * 58500行。

然后,我尝试编辑df,将相等的列id添加到两个要连接的数据帧: val tmpNum = DFNum.withColumn("id", monotonically_increasing_id()) val tmpString = DFString.withColumn("id", monotonically_increasing_id())

并使用:

val df = tmpNum.join(tmpString) 这给我以下错误: USING column `id` cannot be resolved on the left side of the join. The left-side columns:[...]

我还尝试了几种类型的联接(都使用tmpNumtmpString以及DFNumDFString的联接),例如: val df = tmpNum.join(tmpString, Seq("id"), "outer") val df = tmpNum.join(tmpString, Seq("id"), "full_outer")等。 但我总是遇到相同的错误USING column `id` cannot be resolved on the left side of the join. The left-side columns:[...]

(显然使用tmpNumtmpString时,新数据框的总列将增加一列。稍后,我将删除id列)。

如果有人有任何想法或建议,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

如果没有任何键列可以连接2个数据框,则可以依靠monotonically_increasing_id

val a = Seq(("First",1), ("Secound",2), ("Third",3), ("Fourth",4)).toDF("col1", "col2")
val b = Seq(("india",980), ("japan",990), ("korea",1000), ("chaina",900)).toDF("col3", "col4")

a.show

+-------+----+
|   col1|col2|
+-------+----+
|  First|   1|
|Secound|   2|
|  Third|   3|
| Fourth|   4|
+-------+----+

b.show
+------+----+
|  col3|col4|
+------+----+
| india| 980|
| japan| 990|
| korea|1000|
|chaina| 900|
+------+----+

然后将新列添加到两个数据框。确保您的数据框正确排序,否则加入数据框后数据将混乱。

val a1 = a.withColumn("id", monotonically_increasing_id)
val b1 = b.withColumn("id", monotonically_increasing_id)

现在使用id列对两个数据框进行联接,然后删除中间的id

a1.join(b1, Seq("id")).drop("id").show 

+-------+----+------+----+
|   col1|col2|  col3|col4|
+-------+----+------+----+
|  First|   1| india| 980|
|Secound|   2| japan| 990|
|  Third|   3| korea|1000|
| Fourth|   4|chaina| 900|
+-------+----+------+----+

答案 1 :(得分:0)

除非使用笛卡尔坐标,否则在没有匹配数据的情况下无法合并两个数据集。列名不必相同,但列中的值必须相同。如果需要,可以使用它们的所有列联接2个数据框。

val df1 = //a data frame with columns col1-1, col1-2, col1-3
val df2 = //a data frame with columns col2-1, col2-2, col2-3

val dfJoined = df1.join(df2, df1.col1-1===df2.col2-1 or df1.col1-2===df2.col2-2 or df1.col1-3===df2.col2-3)

//Then drop one set of columns if they have same data.

答案 2 :(得分:0)

我最近尝试这样做,但没有成功。您可以尝试将两个对象转换为pandas数据帧,然后进行合并。

步骤1:

df1= df1.select("*").toPandas()
df2= df2.select("*").toPandas()

步骤2:

result = pd.concat([df1, df2], axis=1)

祝你好运!