如何按数组中的公共元素分组?

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]|
// +-----+------------+--------+

【讨论】:

以上是关于如何按数组中的公共元素分组?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB按数组中的元素分组

MongoDB计数按数组元素分组的数组中的匹配字符串

如何按postgres数组中的多个ID分组

MongoDB按数组内部元素分组

如何按不同的值将 clickhouse 中的 (value,count) 数组分组?

如何按特定的子数组值对多维数组进行分组?