Scala Spark Build自定义列函数,用户定义函数
我正在使用Scala,希望构建自己的DataFrame函数。例如,我想把一个列看作一个数组,遍历每个元素并进行计算 首先,我尝试实现我自己的getMax方法。因此,列x的值为[3,8,2,5,9],方法的预期输出为9 这是Scala中的外观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
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"))