我有一个spark数据集,我根据需要将数据分组并减少了数据。我需要摆脱元组,只保留Tuple2 :: _ 2。 我试图按如下方式映射数据集:
sparkSession.read()
.parquet("s3://stuff/*")
.groupByKey((MapFunction<Row, Long>) value -> {
long stamp = value.getAs("timeStamp");
return stamp / 600000;
}, Encoders.LONG())
.reduceGroups((ReduceFunction<Row>) (v1, v2) -> {
int fare1 = v1.getAs("totalFare");
int fare2 = v2.getAs("totalFare");
return fare1 < fare2 ? v1 : v2;
})
.map((MapFunction<Tuple2<Long, Row>, Row>) Tuple2::_2, RowEncoder.apply(null))
无法弄清楚如何向RowEncoder :: apply提供架构。 我正在阅读带有this架构的镶木地板文件。
答案 0 :(得分:2)
所以我最终这样做了。基本上读取1个元素以获得所需的&#34; ExpressionEncoder&#34;。我需要完整的&#34;行&#34;在最终输出中,所以无法继续使用@ Jacek的方法。
System.out.println("Starting");
System.out.println(Arrays.toString(args));
Row sampleRow = sparkSession.read().parquet(readFrom).head();
ExpressionEncoder<Row> rowEncoder = RowEncoder.apply(sampleRow.schema());
//read all elements, process and write back the result
sparkSession.read()
.parquet(readFrom)
.groupByKey((MapFunction<Row, Long>) value -> {
long stamp = value.getAs("timeStamp");
return stamp / 600000;
}, Encoders.LONG())
.reduceGroups((ReduceFunction<Row>) (v1, v2) -> {
int fare1 = v1.getAs("totalFare");
int fare2 = v2.getAs("totalFare");
return fare1 < fare2 ? v1 : v2;
})
.map((MapFunction<Tuple2<Long, Row>, Row>) Tuple2::_2, rowEncoder)
.write()
.parquet(writeTo);
System.out.println("Done !!!!");
答案 1 :(得分:1)
我没有在Spark中使用Java,所以我不能更具体,但......
如果我没弄错,您只想使用timeStamp
和totalFare
字段。 timeStamp
属于long类型,而totalFare
属于int类型。
我的第一个建议是使用as运算符将无类型Row
保留为Dataset[Long, Int]
(在Scala中):
公共数据集为(编码器证据$ 2)返回一个新的数据集,其中每条记录都已映射到指定的类型。
这样你就可以避免处理这些令人不快的Row
对象,你的转换看起来如下:
sparkSession.read()
.parquet("s3://stuff/*")
.as(Encoder...) // <-- I don't know how to write a tuple of (long, int) in Java
完成此操作后,您关于map
的问题将得到&#34;映射&#34;使用Encoders.INT()
如果我没有弄错(试图将我的Scala思维映射到Java&#39; s)。
我提倡使用as
运算符的原因是使用groupByKey
和reduceGroups
对我来说是非常强烈的希望留下无类型的RelationalGroupedDataset API输入KeyValueGroupedDataset。