我有2个数据框需要结合在一起。我们将通过2列进行联接,但是,这2列不是id,并且在其他数据框中不会产生唯一的行值。例如,两个数据框将如下所示:
Dataframe 1
product_no dist code
040 wmn aj
040 wmn lm
040 wmn mn
Dataframe 2
p_no vendor code product
040 wmn ** y
040 wmn *j y
040 wmn mn n
对2列的查询如下:
df1.join(df2, $"product_no" === $"p_no" && $"dist" === $"vendor")
这将使所有行彼此连接并重复。但是,我们也想通过code
进行连接,例如,其中代码等于第二个数据帧中的实际代码。如果找不到实际值,则检查代码是否以j
结尾,如果没有,则我们以*j
加入,如果没有匹配的内容,则以{ {1}}结果应如下所示:
**
有没有办法做到这一点?
答案 0 :(得分:0)
我也经历了一些类似的情况,即基于条件标志进行联接。
val decision: Boolean = false
val exprs = (if (decision != true)
dataFrame1.col("id").equalTo(dataFrame2.col("id"))
else dataFrame1.col("id").equalTo(dataFrame2.col("id"))
and dataFrame1.col("code").equalTo(dataFrame2.col("code")))
)
dataFrame1.join(dataFrame2, exprs).show
您可以看到示例示例here 您可以在此处利用相同的逻辑。
尝试使用行值代替条件标志。
答案 1 :(得分:0)
检查一下:
scala> val df3 = df1.alias("t1").join(df2.alias("t2"),$"product_no" === $"p_no" && $"dist" === $"vendor").withColumn("match", when($"t1.code"===$"t2.code",lit(1)).when(regexp_extract($"t1.code",".*j",0)=!=lit("") && regexp_extract($"t2.code",".*j",0)=!=lit(""), 2).when(regexp_extract($"t1.code",".*[^j]$",0)=!=lit("") && regexp_extract($"t2.code","[*][*]",0)=!=lit(""), 3).otherwise(lit(0))).filter('match > 0).toDF("product_no","dist","code1","p_no","vendor","code2","product","match")
df3: org.apache.spark.sql.DataFrame = [product_no: string, dist: string ... 6 more fields]
scala> val df4= df3.withColumn("match2", collect_set('code2) over(Window.partitionBy('product_no,'dist).orderBy('match)))
df4: org.apache.spark.sql.DataFrame = [product_no: string, dist: string ... 7 more fields]
scala> df4.show
+----------+----+-----+----+------+-----+-------+-----+------------+
|product_no|dist|code1|p_no|vendor|code2|product|match| match2|
+----------+----+-----+----+------+-----+-------+-----+------------+
| 040| wmn| mn| 040| wmn| mn| n| 1| [mn]|
| 040| wmn| aj| 040| wmn| *j| y| 2| [*j, mn]|
| 040| wmn| mn| 040| wmn| **| y| 3|[*j, mn, **]|
| 040| wmn| lm| 040| wmn| **| y| 3|[*j, mn, **]|
+----------+----+-----+----+------+-----+-------+-----+------------+
scala> df4.selectExpr("*"," match in (1,2) or ( not array_contains(match2,code1) ) as match3 ").where('match3).show
+----------+----+-----+----+------+-----+-------+-----+------------+------+
|product_no|dist|code1|p_no|vendor|code2|product|match| match2|match3|
+----------+----+-----+----+------+-----+-------+-----+------------+------+
| 040| wmn| mn| 040| wmn| mn| n| 1| [mn]| true|
| 040| wmn| aj| 040| wmn| *j| y| 2| [*j, mn]| true|
| 040| wmn| lm| 040| wmn| **| y| 3|[*j, mn, **]| true|
+----------+----+-----+----+------+-----+-------+-----+------------+------+
scala>