Spark - 将完整行传递给udf,然后在udf中获取列名

时间:2018-05-22 18:57:49

标签: scala apache-spark

我正在使用Spark和Scala,并希望将整行传递给udf,并选择side udf中的每个列名和列值。我怎么能这样做?

我正在尝试关注 -

inputDataDF.withColumn("errorField", mapCategory(ruleForNullValidation) (col(_*)))

def mapCategory(categories: Map[String, Boolean]) = {
  udf((input:Row) =>  //write a recursive function to check if each row is in categories if yes check for null if null then false, repeat this for all columns and then combine results)   
})

2 个答案:

答案 0 :(得分:3)

在Spark 1.6中,您可以使用Row作为外部类型,使用struct作为表达式。作为表达。可以从架构中获取列名称。例如:

import org.apache.spark.sql.Row
import org.apache.spark.sql.functions.{col, struct}

val df = Seq((1, 2, 3)).toDF("a", "b", "c")
val f = udf((row: Row) => row.schema.fieldNames)
df.select(f(struct(df.columns map col: _*))).show

// +-----------------------------------------------------------------------------+
// |UDF(named_struct(NamePlaceholder, a, NamePlaceholder, b, NamePlaceholder, c))|
// +-----------------------------------------------------------------------------+
// |                                                                    [a, b, c]|
// +-----------------------------------------------------------------------------+

可以使用Row.getAs方法按名称访问值。

答案 1 :(得分:2)

这是一个简单的工作示例:

输入数据:

+-----+---+--------+
| NAME|AGE|CATEGORY|
+-----+---+--------+
|  RIO| 35|     FIN|
|  TOM| 90|     ACC|
|KEVIN| 32|        |
| STEF| 22|     OPS|
+-----+---+--------+

//定义类别列表和UDF

val categoryList = List("FIN","ACC")    
def mapCategoryUDF(ls: List[String]) = udf[Boolean,Row]((x: Row) => if (!ls.contains(x.getAs("CATEGORY"))) false else true)

import org.apache.spark.sql.functions.{struct}
df.withColumn("errorField",mapCategoryUDF(categoryList)(struct("*"))).show()

结果应如下所示:

+-----+---+--------+----------+
| NAME|AGE|CATEGORY|errorField|
+-----+---+--------+----------+
|  RIO| 35|     FIN|      true|
|  TOM| 90|     ACC|      true|
|KEVIN| 32|        |     false|
| STEF| 22|     OPS|     false|
+-----+---+--------+----------+

希望这有帮助!!