如何按数组中的公共元素分组?
Posted
技术标签:
【中文标题】如何按数组中的公共元素分组?【英文标题】:How to group by common element in array? 【发布时间】:2017-05-11 12:43:28 【问题描述】:我正在尝试在 spark 中找到解决方案,以将数据与数组中的公共元素进行分组。
key value
[k1,k2] v1
[k2] v2
[k3,k2] v3
[k4] v4
如果任何元素在key中匹配,我们必须为其分配相同的groupid。(Groupby公共元素)
结果:
key value GroupID
[k1,k2] v1 G1
[k2] v2 G1
[k3,k2] v3 G1
[k4] v4 G2
Spark Graphx 已经给出了一些建议,但目前学习曲线将更多地用于实现单个功能。
【问题讨论】:
我不明白你上面的例子中GroupID
是如何形成的
您是否正在寻找不使用en.wikipedia.org/wiki/Connected_component_(graph_theory) 的解决方案?
@RaphaelRoth GroupID 只是一组数据的唯一 ID。目前我们计划对每个组使用 monotonicallyIncreasingId。
@JacekLaskowski 是的,正如我向您解释的那样,我们没有太多时间来理解和实施图论。尝试使用 spark-core 和 spark-sql 以不同的方式实现相同的目标
我强烈建议您使用预制解决方案,而不是“理解和实施图论”。 Graphframes 可以为您提供帮助:graphframes.github.io/user-guide.html#connected-components
【参考方案1】:
包括 graphframes
(支持的最新 Spark 版本是 2.1,但它也应该支持 2.2,如果您使用较新的版本,则必须使用 2.3 补丁构建自己的版本)将 XXX
替换为 Spark 版本和 @987654324 @ Scala 版本:
spark.jars.packages graphframes:graphframes:0.5.0-sparkXXX-s_YYY
添加爆炸键:
import org.apache.spark.sql.functions._
val df = Seq(
(Seq("k1", "k2"), "v1"), (Seq("k2"), "v2"),
(Seq("k3", "k2"), "v3"), (Seq("k4"), "v4")
).toDF("key", "value")
val edges = df.select(
explode($"key") as "src", $"value" as "dst")
转换为graphframe
:
import org.graphframes._
val gf = GraphFrame.fromEdges(edges)
设置检查点目录(如果没有设置):
import org.apache.spark.sql.SparkSession
val path: String = ???
val spark: SparkSession = ???
spark.sparkContext.setCheckpointDir(path)
查找连通分量:
val components = GraphFrame.fromEdges(edges).connectedComponents.setAlgorithm("graphx").run
将结果与输入数据相结合:
val result = components.where($"id".startsWith("v")).toDF("value", "group").join(df, Seq("value"))
检查结果:
result.show
// +-----+------------+--------+
// |value| group| key|
// +-----+------------+--------+
// | v3|489626271744|[k3, k2]|
// | v2|489626271744| [k2]|
// | v4|532575944704| [k4]|
// | v1|489626271744|[k1, k2]|
// +-----+------------+--------+
【讨论】:
以上是关于如何按数组中的公共元素分组?的主要内容,如果未能解决你的问题,请参考以下文章