如何分解具有可变长度和潜在空值的多个数组列?
我的输入数据如下所示:
+----+------------+--------------+--------------------+
|col1| col2| col3| col4|
+----+------------+--------------+--------------------+
| 1|[id_1, id_2]| [tim, steve]| [apple, pear]|
| 2|[id_3, id_4]| [jenny]| [avocado]|
| 3| null|[tommy, megan]| [apple, strawberry]|
| 4| null| null|[banana, strawberry]|
+----+------------+--------------+--------------------+
我需要将其分解为:
1.具有相同索引的数组项Map到同一行
1.如果一列中只有一个条目,则它将应用于每个分解的行
1.如果数组为空,则应用于每一行
我的输出应该如下所示:
+----+----+-----+----------+
|col1|col2|col3 |col4 |
+----+----+-----+----------+
|1 |id_1|tim |apple |
|1 |id_2|steve|pear |
|2 |id_3|jenny|avocado |
|2 |id_4|jenny|avocado |
|3 |null|tommy|apple |
|3 |null|megan|strawberry|
|4 |null|null |banana |
|4 |null|null |strawberry|
+----+----+-----+----------+
我已经能够使用下面的代码实现这一点,但我觉得必须有一个更直接的方法:
df = spark.createDataFrame(
[
(1, ["id_1", "id_2"], ["tim", "steve"], ["apple", "pear"]),
(2, ["id_3", "id_4"], ["jenny"], ["avocado"]),
(3, None, ["tommy", "megan"], ["apple", "strawberry"]),
(4, None, None, ["banana", "strawberry"])
],
["col1", "col2", "col3", "col4"]
)
df.createOrReplaceTempView("my_table")
spark.sql("""
with cte as (
SELECT
col1,
col2,
col3,
col4,
greatest(size(col2), size(col3), size(col4)) as max_array_len
FROM my_table
), arrays_extended as (
select
col1,
case
when col2 is null then array_repeat(null, max_array_len)
else col2
end as col2,
case
when size(col3) = 1 then array_repeat(col3[0], max_array_len)
when col3 is null then array_repeat(null, max_array_len)
else col3
end as col3,
case
when size(col4) = 1 then array_repeat(col4[0], max_array_len)
when col4 is null then array_repeat(null, max_array_len)
else col4
end as col4
from cte),
arrays_zipped as (
select *, explode(arrays_zip(col2, col3, col4)) as zipped
from arrays_extended
)
select
col1,
zipped.col2,
zipped.col3,
zipped.col4
from arrays_zipped
""").show(truncate=False)
4条答案
按热度按时间sq1bmfud1#
得到
max_array_len
后,只需使用sequence函数遍历数组,将它们转换为一个struct,然后分解得到的struct数组,见下面的SQL:类似的问题here。
wko9yo5t2#
您可以将inline_outer与
selectExpr
结合使用,另外还可以将coalesce
用于第一个非空值,以处理不同数组中的大小不匹配数据准备
内联外部
ssgvzors3#
您可以使用UDF function:
df2
为下列DataFrame
:qmb5sa224#
我用了你的逻辑,把它缩短了一点。
接近步骤
array_repeat
(与您的方法类似)max_size-size({0})
)来计算的arrays_zip
)它们并展开(使用inline()
sql函数)第二个
selectExpr
中的列表解析生成以下内容如果有帮助的话,以下是Spark生成的优化逻辑计划和物理计划