scala - 将 kv 对的 spark 数据帧数组转换为单独的列
问题描述
我有以下架构:
root
|-- id: string (nullable = true)
|-- date: timestamp (nullable = true)
|-- config: struct (nullable = true)
| |-- entry: array (nullable = true)
| | |-- element: struct (containsNull = true)
| | | |-- key: string (nullable = true)
| | | |-- value: string (nullable = true)
数组中不会有超过 3 个键值对 (k1,k2,k3),我想将每个键的值放入自己的列中,而相应的数据将来自同一 kv 对的值。
+--------+----------+----------+----------+---------+
|id |date |k1 |k2 |k3 |
+--------+----------+----------+----------+---------+
| id1 |2019-08-12|id1-v1 |id1-v2 |id1-v3 |
| id2 |2019-08-12|id2-v1 |id2-v2 |id2-v3 |
+--------+----------+----------+----------+---------+
到目前为止,我尝试过这样的事情:
sourceDF.filter($"someColumn".contains("SOME_STRING"))
.select($"id", $"date", $"config.entry" as "kvpairs")
.withColumn($"kvpairs".getItem(0).getField("key").toString(), $"kvpairs".getItem(0).getField("value"))
.withColumn($"kvpairs".getItem(1).getField("key").toString(), $"kvpairs".getItem(1).getField("value"))
.withColumn($"kvpairs".getItem(2).getField("key").toString(), $"kvpairs".getItem(2).getField("value"))
但在这种情况下,列名显示为kvpairs[0][key]
,如下所示:kvpairs[1][key]
kvpairs[2][key]
+--------+----------+---------------+---------------+---------------+
|id |date |kvpairs[0][key]|kvpairs[1][key]|kvpairs[2][key]|
+--------+----------+---------------+---------------+---------------+
| id1 |2019-08-12| id1-v1 | id1-v2 | id1-v3 |
| id2 |2019-08-12| id2-v1 | id2-v2 | id2-v3 |
+--------+----------+---------------+---------------+---------------+
两个问题:
- 我的做法对吗?有没有更好和更简单的方法来旋转这个,这样我每个阵列有一行,3 kv 对作为 3 列?我想处理 kv 对的顺序可能不同的情况。
- 如果上述方法很好,我如何将列名别名为数组中“key”元素的数据?
解决方案
将多个withColumn
与一起使用getItem
将不起作用,因为 kv 对的顺序可能不同。您可以做的是分解数组,然后pivot
按如下方式使用:
sourceDF.filter($"someColumn".contains("SOME_STRING"))
.select($"id", $"date", explode($"config.entry") as "exploded")
.select($"id", $"date", $"exploded.*")
.groupBy("id", "date")
.pivot("key")
.agg(first("value"))
这里聚合内部的用法first
假设每个键都有一个值。否则collect_list
还是collect_set
可以使用的。
结果:
+---+----------+------+------+------+
|id |date |k1 |k2 |k2 |
+---+----------+------+------+------+
|id1|2019-08-12|id1-v1|id1-v2|id1-v3|
|id2|2019-08-12|id2-v1|id2-v2|id2-v3|
+---+----------+------+------+------+
推荐阅读
- ios - `-fobjc-arc-exceptions` compiler flag does not have an effect in Xcode for iOS app
- c# - Add tranparency to huge image C#
- thymeleaf - 百里香叶显示不正确
- mongodb - findAndModify 和 findOneAndUpdate 有什么区别?
- node.js - 使用 Kubernetes 集群在 nGinx 服务器中出现错误的网关 502 错误
- javascript - 将 vue.js 中的结果附加到基于语义 UI 的模板
- css - WorldPay 自定义 css 文件支持的 CSS 属性
- java - VaadinSession 在销毁期间不拥有锁导致 AssertionError
- u-boot - 使用 buildroot 自定义 u-boot 环境变量
- matlab - 如何使用 Octave 对信号进行下采样?