如何将结构数组转换为spark中的结构?
How convert array of struct into struct in spark?
数据集中有一个数组字段,如:
my_array:
[
{id: 1, value: x},
{id: 2, value: y}
]
如何制作:
my_strcut: {
1: {value: x},
2: {value: y}
}
我已经尝试 map_from_entries
和 transform
但仍然有结构数组作为输出。
已更新
有一个数据集从 json 读取数据。这样的数据:
{"id":1, ... "arrayOfStructs" : [{"name": "x", "key":"value"}, {"name": "y", "key":"value2"}]}
输出应该是这样的:
{"id":1, ... "structsOnly" : { "x": {"name": "x", "key":"value"}}, { "y": {"name": "y", "key":"value2"}}}
我认为在这种情况下您想使用 MapType 而不是 StructType,因为结构要求您知道字段 id
的所有值。像这样使用 transform
+ aggregate
函数:
val df1 = df.withColumn(
"structsOnly",
expr("""aggregate(
transform(arrayOfStructs, x -> map(x.name, x)),
cast(map() as map<string,struct<name:string,key:string>>),
(acc, x) -> map_concat(acc, x)
)
""")
).drop("arrayOfStructs")
df1.printSchema
//root
// |-- id: integer (nullable = false)
// |-- structsOnly: map (nullable = true)
// | |-- key: string
// | |-- value: struct (valueContainsNull = true)
// | | |-- name: string (nullable = true)
// | | |-- key: string (nullable = true)
df1.toJSON.show(false)
//+---------------------------------------------------------------------------------------+
//|value |
//+---------------------------------------------------------------------------------------+
//|{"id":1,"structsOnly":{"x":{"name":"x","key":"value"},"y":{"name":"y","key":"value2"}}}|
//+---------------------------------------------------------------------------------------+
现在,如果您真的想要结构类型的列,那么您需要收集字段的所有可能值 key
,然后像这样构建列:
val keys = df1.select(map_keys($"structsOnly")).as[Seq[String]].collect.flatten.distinct
val df2 = df1.withColumn(
"structsOnly",
struct(keys.map(k => col("structsOnly").getField(k).as(k)): _*)
)
数据集中有一个数组字段,如:
my_array:
[
{id: 1, value: x},
{id: 2, value: y}
]
如何制作:
my_strcut: {
1: {value: x},
2: {value: y}
}
我已经尝试 map_from_entries
和 transform
但仍然有结构数组作为输出。
已更新
有一个数据集从 json 读取数据。这样的数据:
{"id":1, ... "arrayOfStructs" : [{"name": "x", "key":"value"}, {"name": "y", "key":"value2"}]}
输出应该是这样的:
{"id":1, ... "structsOnly" : { "x": {"name": "x", "key":"value"}}, { "y": {"name": "y", "key":"value2"}}}
我认为在这种情况下您想使用 MapType 而不是 StructType,因为结构要求您知道字段 id
的所有值。像这样使用 transform
+ aggregate
函数:
val df1 = df.withColumn(
"structsOnly",
expr("""aggregate(
transform(arrayOfStructs, x -> map(x.name, x)),
cast(map() as map<string,struct<name:string,key:string>>),
(acc, x) -> map_concat(acc, x)
)
""")
).drop("arrayOfStructs")
df1.printSchema
//root
// |-- id: integer (nullable = false)
// |-- structsOnly: map (nullable = true)
// | |-- key: string
// | |-- value: struct (valueContainsNull = true)
// | | |-- name: string (nullable = true)
// | | |-- key: string (nullable = true)
df1.toJSON.show(false)
//+---------------------------------------------------------------------------------------+
//|value |
//+---------------------------------------------------------------------------------------+
//|{"id":1,"structsOnly":{"x":{"name":"x","key":"value"},"y":{"name":"y","key":"value2"}}}|
//+---------------------------------------------------------------------------------------+
现在,如果您真的想要结构类型的列,那么您需要收集字段的所有可能值 key
,然后像这样构建列:
val keys = df1.select(map_keys($"structsOnly")).as[Seq[String]].collect.flatten.distinct
val df2 = df1.withColumn(
"structsOnly",
struct(keys.map(k => col("structsOnly").getField(k).as(k)): _*)
)