如何使用JAVA在Spark DataFrame上调用UDF?

时间:2016-02-11 19:13:30

标签: java apache-spark apache-spark-sql user-defined-functions

here类似的问题,但没有足够的观点在那里发表评论。

根据最新的Spark documentationudf可以以两种不同的方式使用,一种使用SQL,另一种使用DataFrame。我找到了多个如何将udf与sql一起使用的示例,但未能找到有关如何直接在DataFrame上使用udf的任何示例。

o.p.提供的解决方案在上面链接的问题上使用__callUDF()__ _deprecated_,并将根据Spark Java API文档在Spark 2.0中删除。在那里,它说:

  

“因为它与udf()”

是多余的

所以这意味着我应该可以使用__udf()__来调用我的udf,但我无法弄清楚如何做到这一点。我没有偶然发现任何说明Java-Spark程序语法的内容。我错过了什么?

import org.apache.spark.sql.api.java.UDF1;
.
.    
UDF1 mode = new UDF1<String[], String>() {
    public String call(final String[] types) throws Exception {
        return types[0];
    }
};

sqlContext.udf().register("mode", mode, DataTypes.StringType);
df.???????? how do I call my udf (mode) on a given column of my DataFrame df?

1 个答案:

答案 0 :(得分:20)

Spark&gt; = 2.3

可以直接调用Scala风格的udf

import static org.apache.spark.sql.functions.*;
import org.apache.spark.sql.expressions.UserDefinedFunction;

UserDefinedFunction mode = udf(
  (Seq<String> ss) -> ss.headOption(), DataTypes.StringType
);

df.select(mode.apply(col("vs"))).show();

Spark&lt; 2.3

即使我们假设您的UDF很有用且无法用简单的getItem调用替换它,它的签名也不正确。使用Scala WrappedArray而不是普通的Java Arrays公开数组列,因此您必须调整签名:

UDF1 mode = new UDF1<Seq<String>, String>() {
  public String call(final Seq<String> types) throws Exception {
    return types.headOption();
  }
};

如果UDF已经注册:

sqlContext.udf().register("mode", mode, DataTypes.StringType);

您只需使用callUDF(这是1.5中引入的新功能)按名称调用它:

df.select(callUDF("mode", col("vs"))).show();

您也可以在selectExprs

中使用它
df.selectExpr("mode(vs)").show();