解析spark中的嵌套json并应用自定义模式

oxf4rvwz  于 2021-05-29  发布在  Spark
关注(0)|答案(1)|浏览(564)

我有下面格式的一行嵌套json

  1. {"2018-10-09": {"CAD": 1.4861, "JPY": 129.45, "NZD": 1.7784, "USD": 1.1435}, "2018-11-30": {"CAD": 1.5116, "JPY": 128.99, "NZD": 1.6556, "USD": 1.1359}}

这只是json的一部分,实际的json非常大。
我需要使用spark读取这个json并做一些预处理。
这是密码

  1. df = spark.read.format("json") \
  2. .option("inferSchema", "true") \
  3. .option("header", 'false') \
  4. .option("sep", ",") \
  5. .load(file_location)
  6. display(df)


架构如下所示

我希望数据看起来像这样

  1. date CAD JPY NZD USD
  2. 2018-01-02 1.51 135.35 1.69 1.2
  3. 2018-01-03 1.50 134.97 1.69 1.209

所以我的新模式应该包含5个字段。
我试着做到如下

  1. df1=df.select("2018-12-27.CAD","2018-12-27.JPY","2018-12-27.NZD","2018-12-27.USD")

但是它需要选择每个日期值,并且有100个日期值。这是痛苦和耗时的。
做这件事的有效方法是什么?

jei2mxaa

jei2mxaa1#

下面的代码是 scala ,您可以将此转换为 python .

  1. scala> df.show(false)
  2. +--------------------------------+--------------------------------+
  3. |2018-10-09 |2018-11-30 |
  4. +--------------------------------+--------------------------------+
  5. |[1.4861, 129.45, 1.7784, 1.1435]|[1.5116, 128.99, 1.6556, 1.1359]|
  6. +--------------------------------+--------------------------------+
  1. scala> val columns = df.columns
  1. scala>
  2. val colExp =
  3. array(
  4. columns
  5. .map(c =>
  6. List(
  7. lit(c).as("date"),
  8. col(s"${c}.*")
  9. )
  10. )
  11. .map(l => struct(l:_*)):_*
  12. )
  1. scala> df.select(explode(colExp).as("data")).select("data.*").show(false)
  2. +----------+------+------+------+------+
  3. |date |CAD |JPY |NZD |USD |
  4. +----------+------+------+------+------+
  5. |2018-10-09|1.4861|129.45|1.7784|1.1435|
  6. |2018-11-30|1.5116|128.99|1.6556|1.1359|
  7. +----------+------+------+------+------+

解释

  1. val colExp =
  2. array(
  3. columns
  4. .map(c => List(lit(c).as("date"),col(s"${c}.*"))) // This one will create `2018-10-09` as `date`, `2018-10-09.*`
  5. .map(l => struct(l:_*)):_* // This will add above columns inside struct(_)
  6. )

上面的代码会给你下面的输出。

  1. array(
  2. struct(
  3. lit("2018-10-09").as(`date`),
  4. col("2018-10-09.*")
  5. ),
  6. struct(
  7. lit("2018-11-30").as(`date`),
  8. col("2018-11-30.*")
  9. )
  10. )

一旦你有了以上的输出,你就很容易做到 explode 数组提取(&E) struct 柱。

展开查看全部

相关问题