Snowball Stemmer只是最后一个词

时间:2011-08-31 21:12:29

标签: r stemming tm

我想使用R中的tm包来阻止纯文本文档语料库中的文档。当我将SnowballStemmer函数应用于语料库的所有文档时,只会阻止每个文档的最后一个单词。

library(tm)
library(Snowball)
library(RWeka)
library(rJava)
path <- c("C:/path/to/diretory")
corp <- Corpus(DirSource(path),
               readerControl = list(reader = readPlain, language = "en_US",
                                    load = TRUE))
tm_map(corp,SnowballStemmer) #stemDocument has the same problem

我认为这与文档被读入语料库的方式有关。用一些简单的例子说明这一点:

> vec<-c("running runner runs","happyness happies")
> stemDocument(vec) 
   [1] "running runner run" "happyness happi" 

> vec2<-c("running","runner","runs","happyness","happies")
> stemDocument(vec2)
   [1] "run"    "runner" "run"    "happy"  "happi" <- 

> corp<-Corpus(VectorSource(vec))
> corp<-tm_map(corp, stemDocument)
> inspect(corp)
   A corpus with 2 text documents

   The metadata consists of 2 tag-value pairs and a data frame
   Available tags are:
     create_date creator 
   Available variables in the data frame are:
     MetaID 

   [[1]]
   run runner run

   [[2]]
   happy happi

> corp2<-Corpus(DirSource(path),readerControl=list(reader=readPlain,language="en_US" ,  load=T))
> corp2<-tm_map(corp2, stemDocument)
> inspect(corp2)
   A corpus with 2 text documents

   The metadata consists of 2 tag-value pairs and a data frame
     Available tags are:
     create_date creator 
   Available variables in the data frame are:
     MetaID 

   $`1.txt`
   running runner runs

   $`2.txt`
   happyness happies

2 个答案:

答案 0 :(得分:4)

加载所需的库

library(tm)
library(Snowball)

创建矢量

vec<-c("running runner runs","happyness happies")

从矢量

创建语料库
vec<-Corpus(VectorSource(vec))

非常重要的是检查我们语料库的类并保留它,因为我们想要一个R函数理解的标准语料库

class(vec[[1]])

vec[[1]]
<<PlainTextDocument (metadata: 7)>>
running runner runs

这可能会告诉你纯文本文件

现在我们修改我们错误的stemDocument函数。首先我们将纯文本转换为字符,然后我们拆分文本,应用现在正常工作的stemDocument并将其粘贴回来。最重要的是,我们将输出重新转换为由tm包给出的PlainTextDocument。

stemDocumentfix <- function(x)
{
    PlainTextDocument(paste(stemDocument(unlist(strsplit(as.character(x), " "))),collapse=' '))
}

现在我们可以在语料库上使用标准的tm_map

vec1 = tm_map(vec, stemDocumentfix)

结果是

vec1[[1]]
<<PlainTextDocument (metadata: 7)>>
run runner run

你需要记住的最重要的事情是始终在语料库中预先发布文档类。 我希望这是使用2个库中的函数来解决问题的简化方法。

答案 1 :(得分:3)

我看到的问题是 wordStem 接受单词的向量,但是Corpus plainTextReader假定在它读取的文档中,每个单词都在它自己的行上。换句话说,这会混淆plainTextReader,因为你最终会在文档中找到3个“单词”

From ancient grudge break to new mutiny,
Where civil blood makes civil hands unclean.
From forth the fatal loins of these two foes

相反,文件应该是

From
ancient
grudge
break
to
new
mutiny
where 
civil
...etc...

另请注意,标点符号也会混淆 wordStem ,因此您也必须将其删除。

在不修改实际文档的情况下执行此操作的另一种方法是定义一个函数,该函数将执行分离并删除在单词之前或之后出现的非字母数字。这是一个简单的:

wordStem2 <- function(x) {
    mywords <- unlist(strsplit(x, " "))
    mycleanwords <- gsub("^\\W+|\\W+$", "", mywords, perl=T)
    mycleanwords <- mycleanwords[mycleanwords != ""]
    wordStem(mycleanwords)
}

corpA <- tm_map(mycorpus, wordStem2);
corpB <- Corpus(VectorSource(corpA));

现在只需使用corpB作为通常的语料库。