如何使用类型化数据集将多值列拆分为单独的行?

时间:2017-04-21 20:19:44

标签: scala apache-spark apache-spark-dataset

我面临的问题是如何将多值列(即List[String])拆分为单独的行。

初始数据集具有以下类型:Dataset[(Integer, String, Double, scala.List[String])]

+---+--------------------+-------+--------------------+
| id|       text         | value |    properties      |
+---+--------------------+-------+--------------------+
|  0|Lorem ipsum dolor...|    1.0|[prp1, prp2, prp3..]|
|  1|Lorem ipsum dolor...|    2.0|[prp4, prp5, prp6..]|
|  2|Lorem ipsum dolor...|    3.0|[prp7, prp8, prp9..]|

结果数据集应具有以下类型:

Dataset[(Integer, String, Double, String)]

并且properties应该拆分为:

+---+--------------------+-------+--------------------+
| id|       text         | value |    property        |
+---+--------------------+-------+--------------------+
|  0|Lorem ipsum dolor...|    1.0|        prp1        |
|  0|Lorem ipsum dolor...|    1.0|        prp2        |
|  0|Lorem ipsum dolor...|    1.0|        prp3        |
|  1|Lorem ipsum dolor...|    2.0|        prp4        |
|  1|Lorem ipsum dolor...|    2.0|        prp5        |
|  1|Lorem ipsum dolor...|    2.0|        prp6        |

3 个答案:

答案 0 :(得分:7)

通常会建议

annotate,但是它来自无类型的DataFrame API并且您使用数据集,我认为pl + annotate(geom="text", x=10, y=1, label = paste0("Value~is~sigma~R^2==", r2.val), parse = TRUE) 运算符可能更合适(请参阅org.apache.spark.sql.Dataset

explode
  

(Scala特定)通过首先将函数应用于此数据集的所有元素,然后展平结果来返回新的数据集。

您可以按如下方式使用它:

flatMap

答案 1 :(得分:4)

您可以使用explode

df.withColumn("property", explode($"property"))

实施例

val df = Seq((1, List("a", "b"))).toDF("A", "B")   
// df: org.apache.spark.sql.DataFrame = [A: int, B: array<string>]

df.withColumn("B", explode($"B")).show
+---+---+
|  A|  B|
+---+---+
|  1|  a|
|  1|  b|
+---+---+

答案 2 :(得分:1)

以下是一种方法:

val myRDD = sc.parallelize(Array(
  (0, "text0", 1.0, List("prp1", "prp2", "prp3")),
  (1, "text1", 2.0, List("prp4", "prp5", "prp6")),
  (2, "text2", 3.0, List("prp7", "prp8", "prp9"))
)).map{
  case (i, t, v, ps) => ((i, t, v), ps)
}.flatMapValues(x => x).map{
  case ((i, t, v), p) => (i, t, v, p)
}