使用不同级别的两个列表分解嵌套 JSON 文件
Explode nested JSON file with two lists at different levels
我有一个 json 文件,布局如下。
{
"$schema": "schema",
"records": [
{
"mode": "1",
"fields": [
{
"name": "id",
"value": "111"
},
{
"name": "name_1a",
"value": "value_1a"
},
{
"name": "name_1b",
"value": "value_1b"
}
]
},
{
"mode": "2",
"fields": [
{
"name": "id",
"value": "222"
},
{
"name": "name_2a",
"value": "value_2a"
},
{
"name": "name_2b",
"value": "value_2b"
}
]
}
],
"format": "json"
}
我正在尝试将其读入 pyspark 数据框以实现以下目标:
id
name
value
111
mode
1
111
name_1a
value_1a
111
name_1b
value_1b
222
mode
2
222
name_2a
value_2a
222
name_2b
value_2b
我已经能够通过 select 适当的键分解出各个元素,例如:
data_fields= data_fields.select('records.mode', 'records.fields')
data_fields = data_fields.select(explode("mode"))
在字段的情况下,我分解了两次以找到较低级别的名称值对。要提取 ids ("111,222")
我 select 从列表中提取该元素,然后使用以下方法再次展开字段:
data_fields = data_fields.withColumn('id', col('fields')[0].value)
但这导致了问题。我不确定如何可靠地将“模式”记录附加到与字段记录相同的格式。
我该怎么做?
内联结构数组后,您可以使用 when
表达式进行一些转换:
from pyspark.sql import functions as F, Window
result = (data_fields.selectExpr("inline(records)")
.selectExpr("mode", "inline(fields)")
.withColumn("id", F.max(F.when(F.col("name") == "id", F.col("value"))).over(Window.partitionBy("mode")))
.withColumn("value", F.when(F.col("name") == "id", F.col("mode")).otherwise(F.col("value")))
.withColumn("name", F.when(F.col("name") == "id", "mode").otherwise(F.col("name")))
.drop("mode")
)
result.show()
#+-------+--------+---+
#| name| value| id|
#+-------+--------+---+
#| mode| 1|111|
#|name_1a|value_1a|111|
#|name_1b|value_1b|111|
#| mode| 2|222|
#|name_2a|value_2a|222|
#|name_2b|value_2b|222|
#+-------+--------+---+
我有一个 json 文件,布局如下。
{
"$schema": "schema",
"records": [
{
"mode": "1",
"fields": [
{
"name": "id",
"value": "111"
},
{
"name": "name_1a",
"value": "value_1a"
},
{
"name": "name_1b",
"value": "value_1b"
}
]
},
{
"mode": "2",
"fields": [
{
"name": "id",
"value": "222"
},
{
"name": "name_2a",
"value": "value_2a"
},
{
"name": "name_2b",
"value": "value_2b"
}
]
}
],
"format": "json"
}
我正在尝试将其读入 pyspark 数据框以实现以下目标:
id | name | value |
---|---|---|
111 | mode | 1 |
111 | name_1a | value_1a |
111 | name_1b | value_1b |
222 | mode | 2 |
222 | name_2a | value_2a |
222 | name_2b | value_2b |
我已经能够通过 select 适当的键分解出各个元素,例如:
data_fields= data_fields.select('records.mode', 'records.fields')
data_fields = data_fields.select(explode("mode"))
在字段的情况下,我分解了两次以找到较低级别的名称值对。要提取 ids ("111,222")
我 select 从列表中提取该元素,然后使用以下方法再次展开字段:
data_fields = data_fields.withColumn('id', col('fields')[0].value)
但这导致了问题。我不确定如何可靠地将“模式”记录附加到与字段记录相同的格式。
我该怎么做?
内联结构数组后,您可以使用 when
表达式进行一些转换:
from pyspark.sql import functions as F, Window
result = (data_fields.selectExpr("inline(records)")
.selectExpr("mode", "inline(fields)")
.withColumn("id", F.max(F.when(F.col("name") == "id", F.col("value"))).over(Window.partitionBy("mode")))
.withColumn("value", F.when(F.col("name") == "id", F.col("mode")).otherwise(F.col("value")))
.withColumn("name", F.when(F.col("name") == "id", "mode").otherwise(F.col("name")))
.drop("mode")
)
result.show()
#+-------+--------+---+
#| name| value| id|
#+-------+--------+---+
#| mode| 1|111|
#|name_1a|value_1a|111|
#|name_1b|value_1b|111|
#| mode| 2|222|
#|name_2a|value_2a|222|
#|name_2b|value_2b|222|
#+-------+--------+---+