[英]Issue with Spark-scala Join . Looking for a better Approach
我有 2 个 DF,如下所示。
+---+---+---+
| M| c2| c3|
+---+---+---+
| 1| 2| 3|
| 2| 3| 4|
+---+---+---+
+---+---+---+
| M| c2| c3|
+---+---+---+
| 1| 20| 30|
| 2| 30| 40|
+---+---+---+
获得如下新数据框的最佳方法应该是什么。这意味着,新的 Df 具有列名 c2 和 c3,但值是concat( df1("c1"),df1("c2") )
但具有相同的列名.我可以用df3.withColumn("c2_new",concat( df1("c2"),df2("c2") ))
做到这一点,然后将新列重命名为 C2。 但问题是我的 DF 中有 150 多个列。这里最好的方法是什么?
+---+------+-----+
| M| c2 | c3 |
+---+-----+------+
| 1| 2_20| 3_30|
| 2| 3_30| 4_40|
+---+------+-----+
如果您有很宽的列,则可以遍历列并对其应用相同的转换。 在您的情况下,您应该像这样合并数据框和聚合列:
import org.apache.spark.sql.types.StringType
val commonColumns = (df1.columns.toSet & df2.columns.toSet).filter(_ != "M").toSeq
commonColumns
df1.union(df2)
.groupBy("M")
.agg(count(lit(1)) as "cnt",
commonColumns.map(c => concat_ws("_", collect_set(col(c).cast(StringType))) as c):_*)
.select("M", commonColumns:_*)
.show
这是输出:
+---+----+----+
| M| c2| c3|
+---+----+----+
| 1|20_2|3_30|
| 2|3_30|40_4|
+---+----+----+
如果您对排序有要求(即来自df1
值必须在左侧,来自df2
值必须在右侧),您可以使用以下技巧:
union
之前添加日期帧编号( 1
和2
)作为新列min
和max
代码:
df1
.withColumn("src", lit(1))
.union(df2.withColumn("src", lit(2)))
.groupBy("M")
.agg(count(lit(1)) as "cnt",
commonColumns.map(c => concat(
min(struct($"src", col(c)))(c),
lit("_"),
max(struct($"src", col(c)))(c)) as c):_*)
.select("M", commonColumns:_*)
.show
最终结果排序:
+---+----+----+
| M| c2| c3|
+---+----+----+
| 1|2_20|3_30|
| 2|3_30|4_40|
+---+----+----+
您可以通过连接来做到这一点:
val selectExpr = df1.columns.filterNot(_=="M").map(c => concat_ws("_",df1(c),df2(c)).as(c))
df1.join(df2,"M")
.select((col("M") +: selectExpr):_*)
.show()
给出:
---+----+----+
| M| c2| c3|
+---+----+----+
| 1|2_20|3_30|
| 2|3_30|4_40|
+---+----+----+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.