【发布时间】:2017-02-05 17:55:14
【问题描述】:
我正在使用 sparkSql 1.6.2 (Java API),我必须处理以下 DataFrame,它在 2 列中有一个值列表:
ID AttributeName AttributeValue
0 [an1,an2,an3] [av1,av2,av3]
1 [bn1,bn2] [bv1,bv2]
想要的表是:
ID AttributeName AttributeValue
0 an1 av1
0 an2 av2
0 an3 av3
1 bn1 bv1
1 bn2 bv2
我想我必须结合使用explode 函数和自定义UDF 函数。
我找到了以下资源:
- Explode (transpose?) multiple columns in Spark SQL table
- How do I call a UDF on a Spark DataFrame using JAVA?
我可以成功运行一个读取两列并返回列中前两个字符串的串联的示例
UDF2 combineUDF = new UDF2<Seq<String>, Seq<String>, String>() {
public String call(final Seq<String> col1, final Seq<String> col2) throws Exception {
return col1.apply(0) + col2.apply(0);
}
};
context.udf().register("combineUDF", combineUDF, DataTypes.StringType);
问题是编写返回两列的 UDF 的签名(在 Java 中)。 据我了解,我必须定义一个新的 StructType 如下所示并将其设置为返回类型,但到目前为止我还没有设法让最终代码正常工作
StructType retSchema = new StructType(new StructField[]{
new StructField("@AttName", DataTypes.StringType, true, Metadata.empty()),
new StructField("@AttValue", DataTypes.StringType, true, Metadata.empty()),
}
);
context.udf().register("combineUDF", combineUDF, retSchema);
任何帮助将不胜感激。
更新:我正在尝试首先实现 zip(AttributeName,AttributeValue),所以我只需要在 sparkSql 中应用标准的 explode 函数:
ID AttName_AttValue
0 [[an1,av1],[an1,av2],[an3,av3]]
1 [[bn1,bv1],[bn2,bv2]]
我构建了以下 UDF:
UDF2 combineColumns = new UDF2<Seq<String>, Seq<String>, List<List<String>>>() {
public List<List<String>> call(final Seq<String> col1, final Seq<String> col2) throws Exception {
List<List<String>> zipped = new LinkedList<>();
for (int i = 0, listSize = col1.size(); i < listSize; i++) {
List<String> subRow = Arrays.asList(col1.apply(i), col2.apply(i));
zipped.add(subRow);
}
return zipped;
}
};
但是当我运行代码时
myDF.select(callUDF("combineColumns", col("AttributeName"), col("AttributeValue"))).show(10);
我收到以下错误消息:
scala.MatchError: [[an1,av1],[an1,av2],[an3,av3]](属于 java.util.LinkedList 类)
看起来组合已正确执行,但返回类型不是 Scala 中的预期类型。
有什么帮助吗?
【问题讨论】:
标签: java apache-spark apache-spark-sql udf