size函数应用于dataframe中的空数组列,在溢出后返回1

guykilcj  于 2021-07-13  发布在  Spark
关注(0)|答案(2)|浏览(281)

注意到了吗 size 使用以下代码对Dataframe中的数组列执行函数-其中包括 split :

import org.apache.spark.sql.functions.{trim, explode, split, size}

val df1 = Seq(
  (1, "[{a},{b},{c}]"),
  (2, "[]"),
  (3, "[{d},{e},{f}]")
).toDF("col1", "col2")
df1.show(false)

val df2 = df.withColumn("cola", split(trim($"col2", "[]"), ",")).withColumn("s", size($"cola"))
df2.show(false)

我们得到:

+----+-------------+---------------+---+
|col1|col2         |cola           |s  |
+----+-------------+---------------+---+
|1   |[{a},{b},{c}]|[{a}, {b}, {c}]|3  |
|2   |[]           |[]             |1  |
|3   |[{d},{e},{f}]|[{d}, {e}, {f}]|3  |
+----+-------------+---------------+---+

我希望得到一个0,以便能够区分0或1个条目。
这里和那里都有一些提示,但没有任何帮助。
如果我有以下条目: (2, null) ,然后我得到-1号,我想这更有用。
另一方面,这个从互联网上借来的样本:

val df = Seq("a" -> Array(1,2,3), "b" -> null, "c" -> Array(7,8,9)).toDF("id","numbers")
df.show
val df2 = df.withColumn("numbers", coalesce($"numbers", array()))
df2.show
val df3 = df2.withColumn("s", size($"numbers"))
df3.show()

按预期返回0。
在这里寻找正确的方法以便得到size=0。

57hvy0tb

57hvy0tb1#

我想根本原因是 split 返回空字符串,而不是null。

scala> df1.withColumn("cola", split(trim($"col2", "[]"), ",")).withColumn("s", $"cola"(0)).select("s").collect()(1)(0)
res53: Any = ""

包含空字符串的数组的大小当然是1。
为了解决这个问题,也许你可以

val df2 = df1.withColumn("cola", split(trim($"col2", "[]"), ","))
             .withColumn("s", when(length($"cola"(0)) =!= 0, size($"cola"))
                              .otherwise(lit(0)))

df2.show(false)
+----+-------------+---------------+---+
|col1|col2         |cola           |s  |
+----+-------------+---------------+---+
|1   |[{a},{b},{c}]|[{a}, {b}, {c}]|3  |
|2   |[]           |[]             |0  |
|3   |[{d},{e},{f}]|[{d}, {e}, {f}]|3  |
+----+-------------+---------------+---+
jmp7cifd

jmp7cifd2#

这个行为继承自java函数split,它在scala和spark中的使用方式相同。空输入是一个特例,在本文中对此进行了详细讨论。
spark设置第二个参数的默认值( limit )的 split 函数为-1。从spark 3开始,我们可以传递一个极限参数 split 功能。
您可以在scala拆分函数与spark sql拆分函数中看到这一点:

"".split(",").length
//res31: Int = 1

spark.sql("""select size(split("", '[,]'))""").show
//+----------------------+
//|size(split(, [,], -1))|
//+----------------------+
//|                     1|
//+----------------------+

",".split(",").length // without setting limit=-1 this gives empty array
//res33: Int = 0

",".split(",", -1).length
//res34: Int = 2

spark.sql("""select size(split(",", '[,]'))""").show
//+-----------------------+
//|size(split(,, [,], -1))|
//+-----------------------+
//|                      2|
//+-----------------------+

相关问题