我想使用自己的令牌生成器对存储为Dataset<String>
的文本进行令牌化,并获取Dataset<Seq<String>>
(以便可以将其传递给CountVectorizer
)。
预期的输入(/tmp/fulltext.txt
):
t1 t2 t3
t4 t5
预期输出:
[t1, t2, t3]
[t4, t5]
我写的令牌生成器是(基本上现在做的事与Spark附带的Tokenizer
相同,但是我需要重写它以支持中文文本的令牌化,因此我不能使用官方的{ {1}}):
Tokenizer
我要制作的Spark应用程序是
public class Utils {
public static Seq<String> segment(String text) {
String[] array = text.split(" ");
List<String> tokens = new ArrayList<>();
for (String term : array) {
tokens.add(term.toLowerCase());
}
return JavaConverters
.asScalaIteratorConverter(tokens.iterator())
.asScala()
.toSeq();
}
}
我是Spark的初学者,上面的代码正是我认为可以使用的代码(在阅读了官方指南之后)。但是事实证明public class TokenizeTest {
public static void main(String[] args) {
SparkSession spark = SparkSession
.builder()
.appName("Tokenize Test")
.getOrCreate();
Dataset<String> rawText = spark
.read()
.textFile("/tmp/fulltext.txt")
.cache();
Encoder<Seq> listEncoder = Encoders.bean(Seq.class);
// Compilation error
Dataset<Seq<String>> newText = rawText
.map((MapFunction<String, Seq<String>>) s -> Utils.segment(s), listEncoder);
newText.show();
spark.stop();
}
}
的代码根本没有编译。您认为有办法解决此问题吗?
答案 0 :(得分:2)
使用这样的Scala集合将无法正常工作。一次Seq
与Bean不兼容,第二次它是通用的。
如果要拆分,只需使用segement
定义为的数组:
public class Utils {
public static String[] segment(String text) {
return text.split(" ");
}
}
和TokenizeTest
定义为:
public class TokenizeTest {
public static void main(String[] args) {
SparkSession spark = SparkSession
.builder()
.appName("Tokenize Test")
.getOrCreate();
Dataset<String> rawText = spark
.read()
.textFile("/path/to/file")
.cache();
Encoder<String []> listEncoder = spark.implicits().newStringArrayEncoder();
Dataset<String []> newText = rawText
.map((MapFunction<String, String []>) s -> Utils.segment(s), listEncoder);
newText.show();
spark.stop();
}
}
在实践中,您可以考虑使用org.apache.spark.sql.functions.split
或org.apache.spark.ml.feature.Tokenizer
而不是重新发明轮子。