Spark Dataframe API:按ID和计算组合分组

时间:2016-04-07 15:48:57

标签: apache-spark spark-dataframe

如何使用SPARK DataFrame API按ID分组,计算组内的所有值组合,并生成单个输出数据框?

示例

val testSchema = StructType(Array(
  StructField("id", IntegerType),
  StructField("value", StringType)))

val test_rows = Seq(
    Row(1, "a"),
    Row(1, "b"),
    Row(1, "c"),
    Row(2, "a"),
    Row(2, "d"),
    Row(2, "e")
)
val test_rdd = sc.parallelize(test_rows)
val test_df = sqlContext.createDataFrame(test_rdd, testSchema)

预期输出

1 a b
1 a c
1 b c
2 a d
2 a e
2 d e

目前为止的最佳解决方案:

执行自联接,过滤id等于并消除相等的值

val result = test_df.join(
    test_df.select(test_df.col("id").as("r_id"), test_df.col("value").as("r_value")),
    ($"id" === $"r_id") and ($"value" !== $"r_value")).select("id", "value", "r_value")


+---+-----+-------+
| id|value|r_value|
+---+-----+-------+
|  1|    a|      b|
|  1|    a|      c|
|  1|    b|      a|
|  1|    b|      c|
|  1|    c|      a|
|  1|    c|      b|
|  2|    a|      d|
|  2|    a|      e|
|  2|    d|      a|
|  2|    d|      e|
|  2|    e|      a|
|  2|    e|      d|
+---+-----+-------+

剩余问题:如何在执行连接时消除重复集,例如(a,b)和(b,a)?

1 个答案:

答案 0 :(得分:1)

您是否对值字段中的对象进行了排序?如果是这样,似乎你可以只加入数据帧,同时要求id相同,左表中的值小于右表中的值。

[edit]如果您没有排序,并且每个ID的值足够少,则另一种解决方案是使用groupByKey,然后根据结果序列创建所有组合,这可以完成比创建所有对更简单,然后只保留一半。 (例如,如果您正在使用Scala,我相信Seq combination函数[doc]将执行您需要的操作。)这会使情况变得更糟而不是大多数数据集的自连接方法。