我的输入数据具有以下格式:
[
{
"id": 123,
"embedded": {
"a": {
"x": true,
"y": 1,
},
"b": {
"x": false,
"y": 2,
},
},
},
{
"id": 456,
"embedded": {
"a": {
"x": false,
"y": 3,
},
"b": {
"x": true,
"y": 4,
},
},
},
]
由于我的pyspark设置有些复杂,embedded
字段是 struct ,上面带有字段a
和b
。尽管将来可能会使用更多的a
和b
键,但我不想将字段列表硬编码到脚本中。
我希望最终数据的格式为:
_______________________________
| id | key | x | y |
_______________________________
| 123 | a | true | 1 |
_______________________________
| 123 | b | false | 2 |
_______________________________
| 456 | a | false | 3 |
_______________________________
| 456 | b | true | 4 |
_______________________________
我知道我想爆炸embedded
字段以获取不同的值,但是如何访问字段名称?
使用下面的PySpark,我可以提取id
,x
和y
列的所有值,但是如何访问结构字段名称({ {1}},a
,...)爆炸时?
b
答案 0 :(得分:1)
如果可能,应改用MapType
df = spark_session.createDataFrame([
Row(id=123, embedded={'a': Row(x=True, y=1), 'b': Row(x=False, y=2)}),
Row(id=456, embedded={'a': Row(x=False, y=3), 'b': Row(x=True, y=4)})
])
df.select(col("id"), explode(col("embedded"))).select(col("id"), col("key"), col("value.*")).show()
输出:
.+---+---+-----+---+
| id|key| x| y|
+---+---+-----+---+
|123| a| true| 1|
|123| b|false| 2|
|456| a|false| 3|
|456| b| true| 4|
+---+---+-----+---+
StructType
绑定到本来是静态的模式。如果您真的想对StructType
执行此操作,则需要以编程方式生成查询
df = spark_session.createDataFrame([
Row(id=123, embedded=Row(a=Row(x=True, y=1), b=Row(x=False, y=2))),
Row(id=456, embedded=Row(a=Row(x=False, y=3), b=Row(x=True, y=4)))
])
field_names = [field.name for field in next(field for field in df.schema.fields if field.name=="embedded").dataType.fields]
dfs = [df.select(col("id"), lit(field_name).alias("key"), col(f"embedded.{field_name}.x"), col(f"embedded.{field_name}.y")) for field_name in field_names]
reduce(lambda x,y: x.union(y), dfs).show()
输出:
+---+---+-----+---+
| id|key| x| y|
+---+---+-----+---+
|123| a| true| 1|
|456| a|false| 3|
|123| b|false| 2|
|456| b| true| 4|
+---+---+-----+---+