gpt4 book ai didi

scala - Spark SQL 嵌套 withColumn

转载 作者:行者123 更新时间:2023-12-02 01:17:40 24 4
gpt4 key购买 nike

我有一个 DataFrame,它有多个列,其中一些是结构。像这样的事情

root
|-- foo: struct (nullable = true)
| |-- bar: string (nullable = true)
| |-- baz: string (nullable = true)
|-- abc: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- def: struct (nullable = true)
| | | |-- a: string (nullable = true)
| | | |-- b: integer (nullable = true)
| | | |-- c: string (nullable = true)

我想在 baz 列上应用 UserDefinedFunction,以将 baz 替换为 baz 函数,但我不知道该怎么做。以下是所需输出的示例(请注意,baz 现在是 int)

root
|-- foo: struct (nullable = true)
| |-- bar: string (nullable = true)
| |-- baz: int (nullable = true)
|-- abc: array (nullable = true)
| |-- element: struct (containsNull = true)
| | |-- def: struct (nullable = true)
| | | |-- a: string (nullable = true)
| | | |-- b: integer (nullable = true)
| | | |-- c: string (nullable = true)

看起来DataFrame.withColumn仅适用于顶级列,但不适用于嵌套列。我正在使用 Scala 来解决这个问题。

有人可以帮我解决这个问题吗?

谢谢

最佳答案

这很简单,只需使用点来选择嵌套结构,例如$“foo.baz”:

case class Foo(bar:String,baz:String)
case class Record(foo:Foo)

val df = Seq(
Record(Foo("Hi","There"))
).toDF()


df.printSchema

root
|-- foo: struct (nullable = true)
| |-- bar: string (nullable = true)
| |-- baz: string (nullable = true)


val myUDF = udf((s:String) => {
// do something with s
s.toUpperCase
})


df
.withColumn("udfResult",myUDF($"foo.baz"))
.show

+----------+---------+
| foo|udfResult|
+----------+---------+
|[Hi,There]| THERE|
+----------+---------+

如果你想将 UDF 的结果添加到现有的 struct foo 中,即得到:

root
|-- foo: struct (nullable = false)
| |-- bar: string (nullable = true)
| |-- baz: string (nullable = true)
| |-- udfResult: string (nullable = true)

有两个选项:

withColumn:

df
.withColumn("udfResult",myUDF($"foo.baz"))
.withColumn("foo",struct($"foo.*",$"udfResult"))
.drop($"udfResult")

使用选择:

df
.select(struct($"foo.*",myUDF($"foo.baz").as("udfResult")).as("foo"))

编辑:用 UDF 的结果替换结构中的现有属性:不幸的是,这不起作用:

df
.withColumn("foo.baz",myUDF($"foo.baz"))

但可以这样做:

// get all columns except foo.baz
val structCols = df.select($"foo.*")
.columns
.filter(_!="baz")
.map(name => col("foo."+name))

df.withColumn(
"foo",
struct((structCols:+myUDF($"foo.baz").as("baz")):_*)
)

关于scala - Spark SQL 嵌套 withColumn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44831789/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com