如何将StructType从Spark中的json数据框分解为行而不是列

Posted

技术标签:

【中文标题】如何将StructType从Spark中的json数据框分解为行而不是列【英文标题】:How to explode StructType to rows from json dataframe in Spark rather than to columns 【发布时间】:2017-11-21 17:18:49 【问题描述】:

我用这个模式读取了一个嵌套的 json:

 root
 |-- company: struct (nullable = true)
 |    |-- 0: string (nullable = true)
 |    |-- 1: string (nullable = true)
 |    |-- 10: string (nullable = true)
 |    |-- 100: string (nullable = true)
 |    |-- 101: string (nullable = true)
 |    |-- 102: string (nullable = true)
 |    |-- 103: string (nullable = true)
 |    |-- 104: string (nullable = true)
 |    |-- 105: string (nullable = true)
 |    |-- 106: string (nullable = true)
 |    |-- 107: string (nullable = true)
 |    |-- 108: string (nullable = true)
 |    |-- 109: string (nullable = true)

当我尝试:

df.select(col("company.*"))

我将结构“公司”的每个字段都作为列。但我希望它们作为行。我想在另一列中获取带有 id 和字符串的行:

  0        1         10       100      101        102 
"hey"   "yooyo"    "yuyu"    "hey"   "yooyo"    "yuyu"

而是得到类似的东西:

id    name
0     "hey"
1     "yoooyo"
10    "yuuy"
100   "hey"
101   "yooyo"
102    "yuyu"

提前感谢您的帮助,

棘手

【问题讨论】:

【参考方案1】:

使用联合试试这个:

val dfExpl = df.select("company.*")

dfExpl.columns
.map(name => dfExpl.select(lit(name),col(name)))
  .reduce(_ union _)
  .show

或者使用数组/爆炸:

val dfExpl = df.select("company.*")
val selectExpr = dfExpl
  .columns
  .map(name =>
    struct(
      lit(name).as("id"),
      col(name).as("value")
    ).as("col")
  )


dfExpl
  .select(
    explode(array(selectExpr: _*))
  )
  .select("col.*")
  .show()

【讨论】:

不知道其他人,但你的第二个解决方案对我的用例来说确实更快。感谢两个解决方案,是不是因为explode针对这种操作进行了优化? 确保import org.apache.spark.sql.functions.explode,lit,struct,array,col 这个答案有 pyspark 版本吗?

以上是关于如何将StructType从Spark中的json数据框分解为行而不是列的主要内容,如果未能解决你的问题,请参考以下文章

将包含 Json 的 Dataset<String> 转换为 Dataset<StructType>

如何在 Spark 中使用 from_json() 数据框?

如何根据 Java Spark 2.1.1 中的字段名称对 structType 进行排序/排序

在 Spark 中执行聚合函数时出错:ArrayType 无法转换为 org.apache.spark.sql.types.StructType

如何在 Spark 中将 Avro Schema 对象转换为 StructType

如何保证 Spark Dataframe 中的重新分区