Map<File, Dataset<Row> allWords = ...
StructField[] structFields = new StructField[] {
new StructField("word", DataTypes.StringType, false, Metadata.empty()),
new StructField("count", DataTypes.IntegerType, false, Metadata.empty()),
new StructField("files", ???, false, Metadata.empty())
};
StructType structType = new StructType(structFields);
Dataset<Row> allFilesWords = spark.createDataFrame(new ArrayList<>(), structType);
for (Map.Entry<File, Dataset<Row>> entry : allWords.entrySet()) {
Integer fileIndex = files.indexOf(entry.getKey());
allFilesWords.unionAll(
allWords.get(entry.getKey()).withColumn("files", ???)
);
}
在上面的给定代码中,allWords
表示从文件到其字数(Row: (string, integer)
)的映射。现在,我想将所有文件的结果聚合到一个DataFrame中,同时保留提到该单词的原始文件。由于最后,每个单词可能已在多个文件中提及,因此files
列旨在整数类型集(假设文件映射为整数)。现在,我正在尝试向allWords
DataFrames添加一个新列,然后使用unionAll
将它们全部合并在一起。
但是我不知道如何使用仅包含一项files
的集合来定义和初始化新列(此处命名为fileIndex
。)
由于评论中提供了链接,我知道我应该使用functions.typedLit
,但是此函数要求输入第二个参数,但我不知道该提供什么。另外,我不知道如何定义列。最后一件事,提供的链接在Python中,而我正在寻找Java API。
答案 0 :(得分:0)
我自己找到了解决方案(在一些帮助下):
Map<File, Dataset<Row> allWords = ...
StructField[] structFields = new StructField[] {
new StructField("word", DataTypes.StringType, false, Metadata.empty()),
new StructField("count", DataTypes.IntegerType, false, Metadata.empty()),
new StructField("files", DataTypes.createArrayType(DataTypes.IntegerType), true, Metadata.empty())
};
StructType structType = new StructType(structFields);
Dataset<Row> allFilesWords = spark.createDataFrame(new ArrayList<>(), structType);
for (Map.Entry<File, Dataset<Row>> entry : allWords.entrySet()) {
Integer fileIndex = files.indexOf(entry.getKey());
allFilesWords.unionAll(
allWords.get(entry.getKey())
.withColumn("files", functions.typedLit(seq, MyTypeTags.SeqInteger()))
);
}
问题是TypeTag
是Scala的编译时工件,根据我在other question中所获得的内容,它必须由Scala编译器生成,无法生成一个用Java。因此,我不得不在Scala文件中编写自定义数据结构的TypeTag
并将其添加到我的Maven Java项目中。为此,我遵循了this article。
这是我的MyTypeTags.scala
文件:
import scala.reflect.runtime.universe._
object MyTypeTags {
val SeqInteger = typeTag[Seq[Integer]]
}