【发布时间】:2017-01-18 23:02:10
【问题描述】:
如何向任何嵌套级别的结构添加或替换字段?
这个输入:
val rdd = sc.parallelize(Seq(
"""{"a": {"xX": 1,"XX": 2},"b": {"z": 0}}""",
"""{"a": {"xX": 3},"b": {"z": 0}}""",
"""{"a": {"XX": 3},"b": {"z": 0}}""",
"""{"a": {"xx": 4},"b": {"z": 0}}"""))
var df = sqlContext.read.json(rdd)
产生以下架构:
root
|-- a: struct (nullable = true)
| |-- XX: long (nullable = true)
| |-- xX: long (nullable = true)
| |-- xx: long (nullable = true)
|-- b: struct (nullable = true)
| |-- z: long (nullable = true)
那么我可以这样做:
import org.apache.spark.sql.functions._
val overlappingNames = Seq(col("a.xx"), col("a.xX"), col("a.XX"))
df = df
.withColumn("a_xx",
coalesce(overlappingNames:_*))
.dropNestedColumn("a.xX")
.dropNestedColumn("a.XX")
.dropNestedColumn("a.xx")
(dropNestedColumn 是从这个答案借来的:
https://stackoverflow.com/a/39943812/1068385。我基本上是在寻找它的逆运算。)
架构变成:
root
|-- a: struct (nullable = false)
|-- b: struct (nullable = true)
| |-- z: long (nullable = true)
|-- a_xx: long (nullable = true)
显然它不会替换(或添加)a.xx,而是在根级别添加新字段a_xx。
我希望能够这样做:
val overlappingNames = Seq(col("a.xx"), col("a.xX"), col("a.XX"))
df = df
.withNestedColumn("a.xx",
coalesce(overlappingNames:_*))
.dropNestedColumn("a.xX")
.dropNestedColumn("a.XX")
这样就会产生这个架构:
root
|-- a: struct (nullable = false)
| |-- xx: long (nullable = true)
|-- b: struct (nullable = true)
| |-- z: long (nullable = true)
我怎样才能做到这一点?
这里的实际目标是对输入 JSON 中的列名不区分大小写。最后一步很简单:收集所有重叠的列名并在每个列上应用合并。
【问题讨论】:
-
你得到解决方案了吗?
-
@ShankarKoirala:不使用 Spark。在 Hive 中,使用 COALESCE 来实现我想要的东西是微不足道的。
标签: scala apache-spark apache-spark-sql spark-dataframe