Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.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 Build自定义列函数,用户定义函数_Scala_Apache Spark_Apache Spark Sql - Fatal编程技术网

Scala Spark Build自定义列函数,用户定义函数

Scala Spark Build自定义列函数,用户定义函数,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我正在使用Scala,希望构建自己的DataFrame函数。例如,我想把一个列看作一个数组,遍历每个元素并进行计算 首先,我尝试实现我自己的getMax方法。因此,列x的值为[3,8,2,5,9],方法的预期输出为9 这是Scala中的外观 def getMax(inputArray: Array[Int]): Int = { var maxValue = inputArray(0) for (i <- 1 until inputArray.length if inputArr

我正在使用Scala,希望构建自己的DataFrame函数。例如,我想把一个列看作一个数组,遍历每个元素并进行计算

首先,我尝试实现我自己的getMax方法。因此,列x的值为[3,8,2,5,9],方法的预期输出为9

这是Scala中的外观

def getMax(inputArray: Array[Int]): Int = {
   var maxValue = inputArray(0)
   for (i <- 1 until inputArray.length if inputArray(i) > maxValue) {
     maxValue = inputArray(i)
   }
   maxValue
}
我不知道还有什么方法可以遍历这个列

def getMax(col: Column): Column = {
var maxValue = col(0)
for (i <- 1 until col.length if col(i) > maxValue){
    maxValue = col(i)
}
maxValue
然后我希望能够在SQL语句中使用它,例如

val sample = sqlContext.sql("SELECT value_max(x) FROM table")
给定输入列[3,8,2,5,9],预期输出为9

我正在关注另一个线程的答案,在那里他们创建了一个标准偏差的私有方法。
我要做的计算将比这更复杂(例如,我将比较列中的每个元素),我是朝着正确的方向走,还是应该更多地研究用户定义的函数?

在Spark数据框中,您不能使用您想到的方法遍历列的元素,因为列不是iterable对象

但是,要处理列的值,您有一些选项,正确的选项取决于您的任务:

1)使用现有的内置功能

Spark SQL已经有很多有用的列处理函数,包括聚合和转换函数。其中大部分可以在
函数
包()中找到。其他一些(通常是二进制函数)可以直接在
列中找到
对象()。因此,如果你能使用它们,它通常是最好的选择注意:不要忘记

2)创建自定义项

如果你不能用内置函数完成任务,你可以考虑定义一个UDF(用户定义函数)。当您可以独立处理列的每个项,并且希望生成与原始列(而不是聚合列)具有相同行数的新列时,它们非常有用。这种方法非常简单:首先,定义一个简单函数,然后将其注册为UDF,然后使用它。例如:

val singleColumnDF = df("column")

val myRDD = singleColumnDF.rdd

// process myRDD
def myFunc:(String=>String)={s=>s.toLowerCase}
导入org.apache.spark.sql.functions.udf
val myUDF=udf(myFunc)
val newDF=df.withColumn(“newCol”),myUDF(df(“oldCol”))
有关更多信息,请参阅一篇精彩的文章

3)使用UDAF

如果您的任务是创建聚合数据,则可以定义UDAF(用户定义的聚合函数)。我在这方面没有太多经验,但我可以为您指出一个不错的教程:

4)退回到RDD处理

如果您确实不能使用上面的选项,或者如果处理任务依赖于不同的行来处理一个任务,并且它不是聚合,那么我认为您必须选择所需的列,并使用相应的RDD来处理它。例如:

val singleColumnDF = df("column")

val myRDD = singleColumnDF.rdd

// process myRDD


所以,我有很多选择。我希望它能有所帮助。

中给出了一个简单的示例,其中一整节专门介绍UDF:

import org.apache.spark.sql._

val df = Seq(("id1", 1), ("id2", 4), ("id3", 5)).toDF("id", "value")
val spark = df.sparkSession
spark.udf.register("simpleUDF", (v: Int) => v * v)
df.select($"id", callUDF("simpleUDF", $"value"))

请显示您的输入和输出/预期数据帧。使用
show
.Hi@JacekLaskowski谢谢你的评论,我已经编辑了这个问题,让它更清楚我想要实现什么。谢谢Daniel,非常有用。所以UDF和UDAF之间的主要区别在于UDAF基于列计算返回一个值?我希望内置函数足以满足我的要求,但最好知道如何实现我自己的函数。@其他15 UDAF通常与
groupBy
一起应用,因此它可以为传递给
groupBy
的列中的每个不同值返回聚合值(类似于简单的
df.groupBy(“key”).agg(avg(“value”))
的工作方式)。但是,如果不使用groupBy,UDAF将只返回一个值。链接重定向到。您不能修复它吗?
import org.apache.spark.sql._

val df = Seq(("id1", 1), ("id2", 4), ("id3", 5)).toDF("id", "value")
val spark = df.sparkSession
spark.udf.register("simpleUDF", (v: Int) => v * v)
df.select($"id", callUDF("simpleUDF", $"value"))