我有一个用我的Spark Java代码编写的UDF,我想在其中传递超过22列(恰好是24列)。但是Spark API仅允许最多22列,是否有任何技巧可以覆盖此列,还是可以创建自定义UDF函数来覆盖此限制?
答案 0 :(得分:0)
您可以传递复杂类型的列。最通用的解决方案是Struct,但您也可以考虑使用Array或Map。
地图示例中的参数:
val df = sc.parallelize(Seq(("a","b"),("c","d"),
("e","f"))).toDF("one","two")
val myUDF = udf((input:Map[String,String]) => {
// do something with the input
input("one")=="a"
})
df
.withColumn("udf_args",map(
lit("one"),$"one",
lit("two"),$"one"
)
)
.withColumn("udf_result", myUDF($"udf_args"))
.show()
答案 1 :(得分:0)
您可以将列值的数组传递给udf,而不是传递24个列值,并且操作将在该数组上。 这是示例代码:
import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions.UserDefinedFunction
case class department(id: Integer, deptname: String)
import spark.implicits._
val df1 = Seq(department(1, "physics")
, department(2, "computer")).toDF()
val df2 = df1.withColumn("all_col", array($"id", $"deptname"))
val concat_udf:UserDefinedFunction = udf((all_col_values:Seq[String]) => {
(all_col_values(0) + "-" + all_col_values(1))
})
//apply udf
val df3 = df2.withColumn("all_col_concat",concat_udf(col("all_col")))
df3.show()
其他: 如果可以在没有udf的情况下在每行上应用匿名函数,则可以尝试这种方式,但是不确定是否可以满足要求。
import org.apache.spark.sql.Row
val df4 = df1.rdd.map{ case Row(id:Integer, deptname:String) => (id, deptname,id.toString()+"-"+deptname)}.
toDF("id","deptname", "all_col_concat")
df4.show()
答案 2 :(得分:0)
我看到很多答案都是用scala编写的,正如您在spark java中所要求的那样,我将用Java重写它。答案也可以在任意列中使用。
import static org.apache.spark.sql.functions.array;
List<Column> cols = Arrays.asList(new Column[] {ds.select("col1"), ds.select("col2") ...});// all the columns
Column mergedCol = array(cols.toArray(new Column[cols.size()])); //merge all your cols
//udf
UserDefinedFunction myUdf = udf(
(Seq<Object> seq) -> {
//you should have 24 Objects here.
for (Object o : JavaConverters.seqAsJavaListConverter(seq).asJava()) {
...
);
},
DataTypes.[your data type]);
//use it as
ds.select(myUdf.apply(mergedCol));