web-dev-qa-db-fra.com

Comment appeler un UDF sur un Spark DataFrame en utilisant JAVA?

Question similaire à ici , mais il n'y a pas assez de points pour commenter là-bas.

Selon le dernier Spark documentation un udf peut être utilisé de deux manières différentes, une avec SQL et une autre avec un DataFrame. J'ai trouvé plusieurs exemples sur la façon d'utiliser un udf avec sql, mais n'ont pu trouver aucun sur la façon d'utiliser un udf directement sur un DataFrame.

La solution apportée par l'o.p. sur la question liée ci-dessus utilise __callUDF()__ qui est _deprecated_ et sera supprimé dans Spark 2.0 selon le Spark Java documentation API. Là, il dit:

"car il est redondant avec udf ()"

cela signifie donc que je devrais être en mesure d'utiliser __udf()__ pour caler mon udf, mais je ne sais pas comment faire cela. Je ne suis tombé sur aucun élément expliquant la syntaxe des programmes Java-Spark. Qu'est-ce que je rate?

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?
14
Kai

Spark> = 2,3

Le style Scala udf peut être appelé directement:

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 <2,3

Même si nous supposons que votre UDF est utile et ne peut pas être remplacé par un simple appel getItem, sa signature est incorrecte. Les colonnes de tableau sont exposées à l'aide de Scala WrappedArray not plain Java Arrays, vous devez donc ajuster la signature:

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

Si UDF est déjà enregistré:

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

vous pouvez simplement utiliser callUDF (qui est une nouvelle fonction introduite en 1.5) pour l'appeler par son nom:

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

Vous pouvez également l'utiliser dans selectExprs:

df.selectExpr("mode(vs)").show();
22
zero323