Apache spark 在Spark中分组行

Apache spark 在Spark中分组行,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,我正在使用Spark 2.4.0,想知道如何使用Spark处理以下问题: 以下数据框中的每个条目可以有两种不同的格式,并提供其ID。我想做的是,如果两个条目共享相同的id(格式1或格式2),将它们分组在一起,并为每个组分配一个组id e、 g 输入数据帧: ------------------------------- Format1 Id | Format2 Id | ------------------------------- Format1_1 | Format2

我正在使用Spark 2.4.0,想知道如何使用Spark处理以下问题:

以下数据框中的每个条目可以有两种不同的格式,并提供其ID。我想做的是,如果两个条目共享相同的id(格式1或格式2),将它们分组在一起,并为每个组分配一个组id

e、 g

输入数据帧:

-------------------------------
Format1 Id    | Format2 Id    |
-------------------------------
Format1_1     |   Format2_1   |
Format1_2     |   Format2_1   |
Format1_3     |   Format2_1   |
Format1_4     |   Format2_2   |
输出数据帧:

-------------------------------------------  
Format1 Id    | Format2 Id    | Group Id   |
-------------------------------------------
Format1_1     |   Format2_1   |  1         |
Format1_2     |   Format2_1   |  1         |
Format1_3     |   Format2_1   |  1         |
Format1_4     |   Format2_2   |  2         |
由于前3个条目在格式2中共享相同的id,因此将它们分组并分配相同的组id

最后一个条目与宝贵的三个条目没有任何关系。它被视为一个单一的群体

我尝试使用HashMap(String,Int)将每个格式id映射到相应的组id,但由于此HashMap没有跨节点分布,因此其他工作节点无法读取以前插入的映射值


我是Spark的新手,想知道如何在Spark中实现这个分组问题?

您可以使用
dense\u rank()
函数

scala> df.show()
+---------+---------+
|      _c0|      _c1|
+---------+---------+
|Format1_1|Format2_1|
|Format1_2|Format2_1|
|Format1_3|Format2_1|
|Format1_4|Format2_2|
+---------+---------+

// dataframe api
scala> df.withColumn("group_id",dense_rank().over(Window.orderBy('_c1))).show()

+---------+---------+--------+
|      _c0|      _c1|group_id|
+---------+---------+--------+
|Format1_1|Format2_1|       1|
|Format1_2|Format2_1|       1|
|Format1_3|Format2_1|       1|
|Format1_4|Format2_2|       2|
+---------+---------+--------+

// sql
scala> spark.sql("select df.*, dense_rank() over (order by _c1) as group_id from df").show()

这可以看作是一个图问题,其中每个id都是一个节点,一对id表示边。因此,任务是找到所有连接的组件,并将组件id追加回原始数据帧

import org.graphframes._ //execute: spark-shell --packages graphframes:graphframes:0.7.0-spark2.4-s_2.11
import spark.implicits._
import org.apache.spark.sql.functions._
import org.apache.spark.sql._

case class Data(id1: Int, id2: Int) 
val data = Seq(Data(1,2), Data(1,3), Data(4,3), Data(4,5)) //sample dataset for testing
val df = data.toDF()

+---+---+
|id1|id2|
+---+---+
|  1|  2|
|  1|  3|
|  4|  3|
|  4|  5|
+---+---+

val nodes = df.select(concat(lit("id1_"), col("id1")).alias("id")).distinct.union(df.select(concat(lit("id2_"), col("id2")).alias("id")).distinct)
val edges = df.select(concat(lit("id1_"), col("id1")).alias("src"), concat(lit("id2_"), col("id2")).alias("dst"))
spark.sparkContext.setCheckpointDir("/tmp/checkpoints")
val g = GraphFrame(nodes, edges)
val comDf = g.connectedComponents.run()

val result = df.withColumn("id", concat(lit("id1_"), col("id1"))).join(comDf, Seq("id"), "left_outer").select("id1","id2","component")

+---+---+------------+
|id1|id2|   component|
+---+---+------------+
|  1|  2|154618822656|
|  1|  3|154618822656|
|  4|  3|154618822656|
|  4|  5|154618822656|
+---+---+------------+

如果行是:a | b c | b c | d e | d e | f,那么它们是否都属于同一组?a | b | 1 c | b | 1 c | d | 1 e | d | 1 e | f | 1是的。这正是我想做的。当
\u c0
有重复项时,这不起作用,因为要求
相同的id(格式1或格式2)
@Eric如果这个答案有效,请接受并投票:)否则让我知道什么不起作用。这个解决方案非常适合我的问题。谢谢@Gsquare,很抱歉接受晚了。