Spark数据帧组合到列表中

时间:2015-08-06 20:00:59

标签: apache-spark dataframe apache-spark-sql spark-dataframe

我正在尝试对集合进行一些分析。我有一个样本数据集,如下所示:

orders.json

{"items":[1,2,3,4,5]}
{"items":[1,2,5]}
{"items":[1,3,5]}
{"items":[3,4,5]}

它只是一个字段,它是一个代表ID的数字列表。

以下是我尝试运行的Spark脚本:

val sparkConf = new SparkConf()
  .setMaster("local[*]")
  .setAppName("Dataframe Test")

val sc = new SparkContext(sparkConf)
val sql = new SQLContext(sc)

val dataframe = sql.read.json("orders.json")

val expanded = dataframe
  .explode[::[Long], Long]("items", "item1")(row => row)
  .explode[::[Long], Long]("items", "item2")(row => row)

val grouped = expanded
  .where(expanded("item1") !== expanded("item2"))
  .groupBy("item1", "item2")
  .count()

val recs = grouped
  .groupBy("item1")

创建expandedgrouped很好,简而言之expanded是两个ID所有可能集合的列表,其中两个ID位于同一个原始集合中。 grouped过滤掉与自身匹配的ID,然后将所有唯一ID组合在一起并为每个ID生成计数。 grouped的架构和数据示例为:

root
 |-- item1: long (nullable = true)
 |-- item2: long (nullable = true)
 |-- count: long (nullable = false)

[1,2,2]
[1,3,2]
[1,4,1]
[1,5,3]
[2,1,2]
[2,3,1]
[2,4,1]
[2,5,2]
...

所以,我的问题是:我现在如何对每个结果中的第一项进行分组,以便我有一个元组列表?对于上面的示例数据,我期望类似于此:

[1, [(2, 2), (3, 2), (4, 1), (5, 3)]]
[2, [(1, 2), (3, 1), (4, 1), (5, 2)]]

正如您在我的脚本recs中看到的那样,我认为您首先要做的就是在' item1'这是每行中的第一项。但是之后你会留下这个GroupedData对象,它对它的操作非常有限。真的,你只剩下像sum,avg等聚合。我只想列出每个结果中的元组。

此时我可以轻松使用RDD功能,但这与使用Dataframes不同。有没有办法使用数据帧功能。

1 个答案:

答案 0 :(得分:11)

您可以使用org.apache.spark.sql.functionscollect_liststruct)构建,自1.6以来可用

val recs =grouped.groupBy('item1).agg(collect_list(struct('item2,'count)).as("set"))


+-----+----------------------------+
|item1|set                         |
+-----+----------------------------+
|1    |[[5,3], [4,1], [3,2], [2,2]]|
|2    |[[4,1], [1,2], [5,2], [3,1]]|
+-----+----------------------------+

您也可以使用collect_set

修改:有关信息,tuples不存在于数据框中。最接近的结构是struct,因为它们相当于无类型数据集API中的案例类。

编辑2:还要注意collect_set附带警告,结果实际上不是一个集合(SQL类型中没有设置属性的数据类型)。这意味着你最终可以得到不同的"集"它们的顺序不同(至少在2.1.0版本中)。然后需要使用sort_array对它们进行排序。