PySpark-爆炸时访问结构字段名称和值

时间:2019-05-20 23:20:08

标签: apache-spark pyspark apache-spark-sql

我的输入数据具有以下格式:

[
  {
    "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 ,上面带有字段ab。尽管将来可能会使用更多的ab键,但我不想将字段列表硬编码到脚本中。

我希望最终数据的格式为:

_______________________________
| id   |  key   |   x   |   y  |
_______________________________
| 123  |  a     |  true |   1  |
_______________________________
| 123  |  b     | false |   2  |
_______________________________
| 456  |  a     | false |   3  |
_______________________________
| 456  |  b     |  true |   4  |
_______________________________

我知道我想爆炸embedded字段以获取不同的值,但是如何访问字段名称?

使用下面的PySpark,我可以提取idxy列的所有值,但是如何访问结构字段名称({ {1}},a,...)爆炸时?

b

1 个答案:

答案 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|
+---+---+-----+---+