gpt4 book ai didi

scala - 如何更新数组列?

转载 作者:行者123 更新时间:2023-12-04 13:44:50 26 4
gpt4 key购买 nike

我知道我们可以替换数据框列中的值并使用以下方法返回一个具有更新值的新数据框:

dataframe.withColumn("col1",when(col("col1").equalTo("this"),"that").otherwise(col("make")))

但这将在需要时更改整个列值。

现在我有一个稍微复杂的数据框:
|        colleagues|   name|

|[guy1, guy2, guy3]|Thisguy|
|[guy4, guy5, guy6]|Thatguy|
|[guy7, guy8, guy9]|Someguy|

在这里,我有一个包含数组的“同事”列。我想替换任何数组的特定元素,例如,在第一行中,我想要在新数据框中使用 'guy10' 而不是 'guy2'
我怎样才能做到这一点?请帮忙。

最佳答案

介绍
在提供最终解决方案之前,有几个问题需要回答(例如,替换一些后 colleagues 数组中元素的顺序),但我不想拖得太久。让我们来看看解决此类问题的非常常见的方法。
解决方案
colleagues column 是一个数组列(并且 Spark 在查询行时非常有效)您应该首先 explode (或 posexplode)它。对于每个数组元素的行,您可以进行必要的更改,最后 collect_list返回数组列。

explode(e: Column): ColumnCreates a new row for each element in the given array or map column.

posexplode(e: Column): ColumnCreates a new row for each element with position in the given array or map column.


让我们使用以下 names数据集:
val names = Seq((Array("guy1", "guy2", "guy3"), "Thisguy")).toDF("colleagues", "name")
scala> names.show
+------------------+-------+
| colleagues| name|
+------------------+-------+
|[guy1, guy2, guy3]|Thisguy|
+------------------+-------+
scala> names.printSchema
root
|-- colleagues: array (nullable = true)
| |-- element: string (containsNull = true)
|-- name: string (nullable = true)
让我们 explode ,做修改,最后 collect_list .
val elements = names.withColumn("elements", explode($"colleagues"))
scala> elements.show
+------------------+-------+--------+
| colleagues| name|elements|
+------------------+-------+--------+
|[guy1, guy2, guy3]|Thisguy| guy1|
|[guy1, guy2, guy3]|Thisguy| guy2|
|[guy1, guy2, guy3]|Thisguy| guy3|
+------------------+-------+--------+
这就是 Spark SQL 可以轻松处理的事情。让我们使用 regexp_replace (什么?正则表达式?!现在你有两个问题:))。
val replaced = elements.withColumn("replaced", regexp_replace($"elements", "guy2", "guy10"))
scala> replaced.show
+------------------+-------+--------+--------+
| colleagues| name|elements|replaced|
+------------------+-------+--------+--------+
|[guy1, guy2, guy3]|Thisguy| guy1| guy1|
|[guy1, guy2, guy3]|Thisguy| guy2| guy10|
|[guy1, guy2, guy3]|Thisguy| guy3| guy3|
+------------------+-------+--------+--------+
最后,让我们按初始数组列分组并使用 collect_list分组功能。
val solution = replaced
.groupBy($"colleagues" as "before")
.agg(
collect_list("replaced") as "after",
first("name") as "name")
scala> solution.show
+------------------+-------------------+-------+
| before| after| name|
+------------------+-------------------+-------+
|[guy1, guy2, guy3]|[guy1, guy10, guy3]|Thisguy|
+------------------+-------------------+-------+
替代解决方案
用户定义函数 (UDF)
或者,您也可以编写一个自定义的用户定义函数,但这不会像上面的解决方案那样从尽可能多的优化中受益,所以我不推荐它(并且只会根据要求显示)。
自定义逻辑运算符
最好的方法是编写一个自定义逻辑运算符(一个 LogicalPlan )来完成所有这些并参与优化,但避免交换(由 groupBy 引入)。然而,这将是一个相当先进的 Spark 开发,我还没有完成。

关于scala - 如何更新数组列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50637795/

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