如何将一行数组平面映射为多行?

时间:2015-06-14 19:30:52

标签: apache-spark apache-spark-sql

在解析了一些jsons后,我有一个数组的单列DataFrame

scala> val jj =sqlContext.jsonFile("/home/aahu/jj2.json")
res68: org.apache.spark.sql.DataFrame = [r: array<bigint>]
scala> jj.first()
res69: org.apache.spark.sql.Row = [List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]

我想把每一行分成几行。怎么样?

修改

原始json文件:

{"r": [0,1,2,3,4,5,6,7,8,9]}
{"r": [0,1,2,3,4,5,6,7,8,9]}

我想要一个包含20行的RDD或DataFrame。

我不能简单地在这里使用flatMap - 我不确定spark中的相应命令是什么:

scala> jj.flatMap(r => r)
<console>:22: error: type mismatch;
 found   : org.apache.spark.sql.Row
 required: TraversableOnce[?]
              jj.flatMap(r => r)

3 个答案:

答案 0 :(得分:4)

您可以使用DataFrame.explode来达到您的目标。下面是我在你的示例json数据中使用spark-shell尝试的内容。

import scala.collection.mutable.ArrayBuffer
val jj1 = jj.explode("r", "r1") {list : ArrayBuffer[Long] => list.toList }
val jj2 = jj1.select($"r1")
jj2.collect

您可以参考API文档来了解更多DataFrame.explode

答案 1 :(得分:3)

我已经使用Spark 1.3.1对此进行了测试 或者您可以使用Row.getAs函数:

import scala.collection.mutable.ArrayBuffer
val elementsRdd = jj.select(jj("r")).map(t=>t.getAs[ArrayBuffer[Long]](0)).flatMap(x=>x)
elementsRdd.count()
>>>Long = 20
elementsRdd.take(5)
>>>Array[Long] = Array(0, 1, 2, 3, 4)

答案 2 :(得分:2)

在Spark 1.3+中,您可以直接在感兴趣的列上使用explode函数:

import org.apache.spark.sql.functions.explode

jj.select(explode($"r"))