将(键,值)的结构Arary拆分为多列

时间:2020-01-07 21:00:24

标签: scala apache-spark apache-spark-sql

我有一个数据帧,其中一列为array<struct<key:string, value: string>>。我想将该列分解为多个列,其中key元素的值成为这些列的名称,而value元素的值成为那些基于key的列的值。也许图片可以更好地说明这一点:

给出列c的列[[name, John], [role, admin], [created_at, 1555757657654]],我想要一个具有以下结构的数据框:

+------+-------+---------------+
| name | role  | created_at    |
+------+-------+---------------+
| John | admin | 1555757657654 |
+------+-------+---------------+

要使问题进一步复杂化,列c的不同行可能具有不同的键集,并且所有这些键都必须成为列,对于缺少相应键的行设置为null。

P.S。为了解决XY Problem,我想根据键和值有效地查询行。我尝试使用array_contains函数检查数组中键的存在,但是发现性能不足。

1 个答案:

答案 0 :(得分:1)

如果我正确理解您的要求,则应该进行groupBy/pivot转换:

case class KV(key: String, value: String)

val df = Seq(
  (1, Seq(KV("name", "John"), KV("role", "admin"))),
  (2, Seq(KV("name", "Rachel"), KV("role", "user"))),
  (3, Seq(KV("name", "Dave"), KV("created_at", "1555757657654")))
).toDF("id", "kvs")

df.
  withColumn("kv", explode($"kvs")).
  groupBy($"id").pivot($"kv.key").agg(first($"kv.value")).
  show
// +---+-------------+------+-----+
// | id|   created_at|  name| role|
// +---+-------------+------+-----+
// |  1|         null|  John|admin|
// |  3|1555757657654|  Dave| null|
// |  2|         null|Rachel| user|
// +---+-------------+------+-----+