Java 如何使用StopWordsRemover转换json对象的数据帧?

Java 如何使用StopWordsRemover转换json对象的数据帧?,java,json,apache-spark,Java,Json,Apache Spark,我正在使用MLlib和Spark 1.5.1。输入类型必须为ArrayType(StringType),但必须为StringType。我的代码有什么问题 StopWordsRemover remover = new StopWordsRemover() .setInputCol("text") .setOutputCol("filtered"); DataFrame df = sqlContext.re

我正在使用MLlib和Spark 1.5.1。输入类型必须为ArrayType(StringType),但必须为StringType。我的代码有什么问题

StopWordsRemover remover = new StopWordsRemover()
                       .setInputCol("text")
                       .setOutputCol("filtered");

DataFrame df = sqlContext.read().json("file:///home/ec2-user/spark_apps/article.json");

System.out.println("***DATAFRAME SCHEMA: " + df.schema());

DataFrame filteredTokens = remover.transform(df);
filteredTokens.show();
输出:

***DATAFRAME SCHEMA: StructType(StructField(doc_id,LongType,true), StructField(image,StringType,true), StructField(link_title,StringType,true), StructField(sentiment_polarity,DoubleType,true), StructField(sentiment_subjectivity,DoubleType,true), StructField(text,StringType,true), StructField(url,StringType,true))
错误:

Exception in thread "main" java.lang.IllegalArgumentException: requirement failed: Input type must be ArrayType(StringType) but got StringType.
    at scala.Predef$.require(Predef.scala:233)
    at org.apache.spark.ml.feature.StopWordsRemover.transformSchema(StopWordsRemover.scala:149)
    at org.apache.spark.ml.feature.StopWordsRemover.transform(StopWordsRemover.scala:129)
    at com.bah.ossem.spark.topic.LDACountVectorizer.main(LDACountVectorizer.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:672)
    at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:180)
    at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:205)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:120)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
article.json(第1行)

编辑:用java实现了zero323的scala代码,效果非常好。谢谢你

Tokenizer tokenizer = new Tokenizer().setInputCol("text").setOutputCol("words");

StopWordsRemover remover = new StopWordsRemover().setInputCol("words").setOutputCol("filtered");

DataFrame jsondf = sqlContext.read().json("file:///home/ec2-user/spark_apps/article.json");

DataFrame wordsDataFrame = tokenizer.transform(jsondf);

DataFrame filteredTokens = remover.transform(wordsDataFrame);
filteredTokens.show();

CountVectorizerModel cvModel = new CountVectorizer()
        .setInputCol("filtered").setOutputCol("features")
        .setVocabSize(10).fit(filteredTokens);
cvModel.transform(filteredTokens).show();

嗯,错误消息是不言自明的
StopWordsRemover
需要
字符串的
数组
作为输入,而不是
字符串
。这意味着您必须首先标记数据。使用Scala API:

import org.apache.spark.ml.feature.Tokenizer
导入org.apache.spark.ml.feature.StopWordsRemover
导入org.apache.spark.sql.DataFrame
val标记器:标记器=新标记器()
.setInputCol(“文本”)
.setOutputCol(“原始令牌”)
val remover:StopWordsRemover=新的StopWordsRemover()
.setInputCol(“原始令牌”)
.setOutputCol(“令牌”)
val标记化:DataFrame=tokenizer.transform(df)
val filtered:DataFrame=remover.transform(标记化)

嗯,错误消息是不言自明的
StopWordsRemover
需要
字符串的
数组
作为输入,而不是
字符串
。这意味着您必须首先标记数据。使用Scala API:

import org.apache.spark.ml.feature.Tokenizer
导入org.apache.spark.ml.feature.StopWordsRemover
导入org.apache.spark.sql.DataFrame
val标记器:标记器=新标记器()
.setInputCol(“文本”)
.setOutputCol(“原始令牌”)
val remover:StopWordsRemover=新的StopWordsRemover()
.setInputCol(“原始令牌”)
.setOutputCol(“令牌”)
val标记化:DataFrame=tokenizer.transform(df)
val filtered:DataFrame=remover.transform(标记化)

是的,谢谢。我认为输入应该是一个令牌串。嗯,我现在明白了。不过,在Java中看到这一点会很好,因为我用了一种迂回的方法来标记列,同时仍然在dataframe中包含不需要标记的其他数据。我实现了与上面scala代码完全相同的Java版本,它工作得非常好,dataframe仍然保留了所有内容。我认为标记化数据帧中唯一的列是我指定的inputcol。非常感谢。我明白了你在这个问题上的帮助:这是为LDA创建语料库的正确方法吗?是的,谢谢。我认为输入应该是一个令牌串。嗯,我现在明白了。不过,在Java中看到这一点会很好,因为我用了一种迂回的方法来标记列,同时仍然在dataframe中包含不需要标记的其他数据。我实现了与上面scala代码完全相同的Java版本,它工作得非常好,dataframe仍然保留了所有内容。我认为标记化数据帧中唯一的列是我指定的inputcol。非常感谢。我明白了你在这个问题上的帮助:这是为LDA创建语料库的正确方法吗?
Tokenizer tokenizer = new Tokenizer().setInputCol("text").setOutputCol("words");

StopWordsRemover remover = new StopWordsRemover().setInputCol("words").setOutputCol("filtered");

DataFrame jsondf = sqlContext.read().json("file:///home/ec2-user/spark_apps/article.json");

DataFrame wordsDataFrame = tokenizer.transform(jsondf);

DataFrame filteredTokens = remover.transform(wordsDataFrame);
filteredTokens.show();

CountVectorizerModel cvModel = new CountVectorizer()
        .setInputCol("filtered").setOutputCol("features")
        .setVocabSize(10).fit(filteredTokens);
cvModel.transform(filteredTokens).show();