我有一个数据帧,其中一列为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
函数检查数组中键的存在,但是发现性能不足。
答案 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|
// +---+-------------+------+-----+