在Spark中独立爆炸多个列

时间:2019-05-15 19:14:30

标签: scala apache-spark

我有一个架构,其中每一行包含多个数组列,并且我想彼此独立地展开每个数组列。

假设我们有以下列:

**userId    someString      varA     varB       someBool
   1        "example1"    [0,2,5]   [1,2,9]        true
   2        "example2"    [1,20,5]  [9,null,6]     false

我想要输出:

userId    someString      varA     varB   someBool
   1      "example1"       0        null    true
   1      "example1"       2        null    true
   1      "example1"       5        null    true
   1      "example1"       1        null    true
   1      "example1"       20       null    true
   1      "example1"       5        null    true
   2      "example2"       null      1      false
   2      "example2"       null      2      false
   2      "example2"       null      9      false
   2      "example2"       null      9      false
   2      "example2"       null     null    false
   2      "example2"       null      6      false

想法?

(哦,我正在尝试对此进行一般性处理,因此我不必在架构更改时更新代码,也不必因为 actual 架构很大……)< / p>

PS-对this的支持与我非常无耻地偷走了示例数据的问题非常相似,但又不同。

编辑:@oliik获胜,但是用df.flatMap来解决这个问题也很棒(主要是因为我仍然不喜欢flatMap

1 个答案:

答案 0 :(得分:5)

您始终可以通过编程方式生成选择

val df = Seq(
  (1, "example1", Seq(0,2,5), Seq(Some(1),Some(2),Some(9)), true),
  (2, "example2", Seq(1,20,5), Seq(Some(9),Option.empty[Int],Some(6)), false)
).toDF("userId", "someString", "varA", "varB", "someBool")

val arrayColumns = df.schema.fields.collect {
  case StructField(name, ArrayType(_, _), _, _) => name
}

val dfs = arrayColumns.map { expname =>
  val columns = df.schema.fields.map {
    case StructField(name, ArrayType(_, _), _, _) if expname == name => explode(df.col(name)) as name
    case StructField(name, ArrayType(_, _), _, _) => lit(null) as name
    case StructField(name, _, _, _) => df.col(name)
  }
  df.select(columns:_*)
}

dfs.reduce(_ union _).show()
+------+----------+----+----+--------+
|userId|someString|varA|varB|someBool|
+------+----------+----+----+--------+
|     1|  example1|   0|null|    true|
|     1|  example1|   2|null|    true|
|     1|  example1|   5|null|    true|
|     2|  example2|   1|null|   false|
|     2|  example2|  20|null|   false|
|     2|  example2|   5|null|   false|
|     1|  example1|null|   1|    true|
|     1|  example1|null|   2|    true|
|     1|  example1|null|   9|    true|
|     2|  example2|null|   9|   false|
|     2|  example2|null|null|   false|
|     2|  example2|null|   6|   false|
+------+----------+----+----+--------+