Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 从Spark DataFrame列中的数组中获取最小值_Scala_Apache Spark - Fatal编程技术网

Scala 从Spark DataFrame列中的数组中获取最小值

Scala 从Spark DataFrame列中的数组中获取最小值,scala,apache-spark,Scala,Apache Spark,我有一个带有数组的数据帧 val DF = Seq( ("123", "|1|2","3|3|4" ), ("124", "|3|2","|3|4" ) ).toDF("id", "complete1", "complete2") .select($"id", split($"complete1", "\\|").as("complete1"), split($"complete2", "\\|").as("complete2")) |id |complete1|c

我有一个带有数组的数据帧

val DF = Seq(
  ("123", "|1|2","3|3|4" ),
  ("124", "|3|2","|3|4" )
).toDF("id", "complete1", "complete2")
.select($"id", split($"complete1", "\\|").as("complete1"), split($"complete2", "\\|").as("complete2"))

|id           |complete1|complete2|
+-------------+---------+---------+
|          123| [, 1, 2]|[3, 3, 4]|
|          124| [, 3, 2]| [, 3, 4]|
+-------------+---------+---------+
如何提取每个数组的最小值

|id           |complete1|complete2|
+-------------+---------+---------+
|          123| 1       | 3       |
|          124| 2       | 3       |
+-------------+---------+---------+
我已经尝试定义一个UDF来实现这一点,但我得到了一个错误

def minArray(a:Array[String]) :String = a.filter(_.nonEmpty).min.mkString
val minArrayUDF = udf(minArray _)   
def getMinArray(df: DataFrame, i: Int): DataFrame = df.withColumn("complete" + i, minArrayUDF(df("complete" + i)))

val minDf = (1 to 2).foldLeft(DF){ case (df, i) => getMinArray(df, i)}

java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String;

您可以如下定义您的
udf
函数

def minUdf = udf((arr: Seq[String])=> arr.filterNot(_ == "").map(_.toInt).min)
并称之为

DF.select(col("id"), minUdf(col("complete1")).as("complete1"), minUdf(col("complete2")).as("complete2")).show(false)
应该给你什么

+---+---------+---------+
|id |complete1|complete2|
+---+---------+---------+
|123|1        |3        |
|124|2        |3        |
+---+---------+---------+
已更新

如果传递给udf函数的数组为空或空字符串数组,则会遇到

java.lang.UnsupportedOperationException:empty.min

您应该使用
udf
函数as中的
if-else
条件来处理该问题

def minUdf = udf((arr: Seq[String])=> {
  val filtered = arr.filterNot(_ == "")
  if(filtered.isEmpty) 0
  else filtered.map(_.toInt).min
})

我希望答案是有帮助的

以下是不使用
udf

首先
分解
使用
split()
得到的数组,然后按相同的id分组并找到
min

  val DF = Seq(
    ("123", "|1|2","3|3|4" ),
    ("124", "|3|2","|3|4" )
  ).toDF("id", "complete1", "complete2")
    .select($"id", split($"complete1", "\\|").as("complete1"), split($"complete2", "\\|").as("complete2"))
    .withColumn("complete1", explode($"complete1"))
    .withColumn("complete2", explode($"complete2"))
    .groupBy($"id").agg(min($"complete1".cast(IntegerType)).as("complete1"), min($"complete2".cast(IntegerType)).as("complete2"))
输出:

+---+---------+---------+
|id |complete1|complete2|
+---+---------+---------+
|124|2        |3        |
|123|1        |3        |
+---+---------+---------+

您不需要自定义项,可以使用
sort\u array

val DF = Seq(
  ("123", "|1|2","3|3|4" ),
  ("124", "|3|2","|3|4" )
).toDF("id", "complete1", "complete2")
  .select(
    $"id",
    split(regexp_replace($"complete1","^\\|",""), "\\|").as("complete1"),
    split(regexp_replace($"complete2","^\\|",""), "\\|").as("complete2")
  )


// now select minimum
DF.
 .select(
  $"id",
  sort_array($"complete1")(0).as("complete1"),
  sort_array($"complete2")(0).as("complete2")
).show()

+---+---------+---------+
| id|complete1|complete2|
+---+---------+---------+
|123|        1|        3|
|124|        2|        3|
+---+---------+---------+

请注意,我在拆分之前删除了前导的
|
,以避免数组中出现空字符串

自Spark 2.4以来,您可以使用来查找数组中的最小值。要使用此函数,首先必须将字符串数组转换为整数数组。强制转换还将通过将空字符串转换为
null
值来处理空字符串

DF.选择($“id”,
数组(expr(“cast(complete1作为数组)”).as(“complete1”),
数组(expr(“cast(complete2作为数组)”).as(“complete2”))

这非常有效!如何处理空数组[,,]?java.lang.UnsupportedOperationException:empty.minI在我的数组中没有空字符串。有些只是空的。