【问题标题】:Spark : Explode a pair of nested columnsSpark:爆炸一对嵌套列
【发布时间】:2019-01-15 03:02:12
【问题描述】:

Spark 2.1 版

我正在将文件读入 Spark dataframe,格式如下:

{
    "field1": "value1",
    "field2": "value2",
    "elements": [{
        "id": "1",
        "name": "a"
    },
    {
        "id": "2",
        "name": "b"
    },
    {
        "id": "3",
        "name": "c"
    }]
}

它包含一个array的嵌套元素,现在我想explodeelements数组来获得扁平的json结构。我正在使用以下代码:

var dfExploded = df
    .withColumn("id", 
      explode(df.col("elements.id")))
    .withColumn("name",
      explode(df.col("elements.name")));

它似乎正在返回笛卡尔积(例如,我在结果中得到 9 个元素,而我只想要 3 个)。有什么方法可以为explode 函数指定一对嵌套列?

【问题讨论】:

  • 也许把 Id + name 变成元组?

标签: scala apache-spark apache-spark-sql


【解决方案1】:

如果我理解正确,你会希望你可以试试这个:

 val exploded = df.withColumn("elements", explode($"elements"))
 exploded.show()
 >> +--------+------+------+
 >> |elements|field1|field2|
 >> +--------+------+------+
 >> |   [1,a]|value1|value2|
 >> |   [2,b]|value1|value2|
 >> |   [3,c]|value1|value2|
 >> +--------+------+------+

这第一步基本上将数组转换为单独的记录。您需要对数组本身(元素)而不是里面的元素进行操作

接下来你可以做

 val flattened = exploded.select("elements.*", "field1", "field2")
 flattened.show()
 >> +---+----+------+------+
 >> | id|name|field1|field2|
 >> +---+----+------+------+
 >> |  1|   a|value1|value2|
 >> |  2|   b|value1|value2|
 >> |  3|   c|value1|value2|
 >> +---+----+------+------+

扁平化元素

【讨论】:

  • 感谢您的意见。现在我了解了单个 explode 与 select 和多个 explode 调用之间的区别。像魅力一样工作:)
  • 很好的答案,我可以进一步问,如果没有“id”元素并且必须提取它(例如使用posexplode)作为数组elements中的顺序,如何管理?
  • @PavelProchazka 你能举个例子吗?
  • 就像前面提到的带有{"field1": "value1", "field2": "value2", "elements": [{"name": "a" }, {"name": "b"}, { "name": "c" }]}给出的数据框的例子,没有id。所需的结果与您的答案中的flattened 完全相同,其中 id 按数组中的顺序给出。
  • @PavelProchazka 你可以试试这样的: df.select($"field1", $"field2", posexplode($"elements").as(Seq("id", "extracted" ))).select($"field1", $"field2", $"id", $"extracted.*").show()
猜你喜欢
  • 1970-01-01
  • 2017-01-09
  • 2016-11-09
  • 1970-01-01
  • 2018-06-20
  • 2022-01-16
  • 1970-01-01
  • 2019-10-18
相关资源
最近更新 更多