分组使用Spark Scala在两个不同的DataFrame中使用两个不同的键而不加入

时间:2017-06-14 19:28:01

标签: scala apache-spark rdd

我是Spark Scala的新手,我想使用两个数据帧或RDD来计算相似性变量。我没有在他们两个之间有一个共同的关键,​​我做了一个笛卡尔联合但加入的Df是巨大的。是否有可能从两个DF计算一个新变量而不加入它们?

例如:

df1.show
+----+------------+------+
| id1|        food| level|
+----+------------+------+
|id11|       pasta| first|
|id11|       pizza|second|
|id11|   ice cream| first|
|id12|     spanish| first|
|id12|   ice cream|second|
|id13|      fruits| first|
+----+------------+------+
df2.show
+----+---------+
| id2|     food|
+----+---------+
|id21|    pizza|
|id21|   fruits|
|id22|    pasta|
|id22|    pizza|
|id22|ice cream|
+----+---------+

对于来自df1的每个id1,我想通过id2从df2分组循环食物变量 我想得到这个输出:

+----+----+----------------+
| id1| id2|count_similarity|
+----+----+----------------+
|id11|id21|               1|id11 and id21 have only "pizza' in common
|id11|id22|               3|
|id12|id21|               0|
|id12|id22|               1|
|id13|id21|               1|
|id13|id22|               0|
+----+----+----------------+

是否可以使用RDD上的地图句子来计算? 谢谢

2 个答案:

答案 0 :(得分:0)

您可以将两个数据帧都转换为rdd,使用cartesian方法计算每个ID对之间的相似度,然后重建数据框:

case class similarity(id1: String, id2: String, count_similarity: Int)

val rdd1 = df1.rdd.groupBy(_.getString(0)).mapValues(_.map(_.getString(1)).toList)    
val rdd2 = df2.rdd.groupBy(_.getString(0)).mapValues(_.map(_.getString(1)).toList)

rdd1.cartesian(rdd2).map{ 
    case (x, y) => similarity(x._1, y._1, x._2.intersect(y._2).size) 
}.toDF.orderBy("id1").show

+----+----+----------------+
| id1| id2|count_similarity|
+----+----+----------------+
|id11|id22|               3|
|id11|id21|               1|
|id12|id21|               0|
|id12|id22|               1|
|id13|id21|               1|
|id13|id22|               0|
+----+----+----------------+

答案 1 :(得分:0)

这对你有用吗?

if