Snowball词干提取器只对最后一个单词进行词干提取

7

我希望使用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

Rstem不是R接口到Snowball吗?因此,您应该使用library(Rstem)并尝试tm_map(corp, wordStem)。 - Apprentice Queue
感谢您的评论。我尝试了一下,结果还是一样的。我会在上面加入一个更好的例子来更好地说明问题。 - Christian
2个回答

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

你需要记住的最重要的事情是始终保留语料库中文档的类。我希望这个问题能够得到简化的解决方案,使用加载的两个库中的函数。


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用作您通常的语料库即可。

谢谢,现在词干处理成功了。不过应用wordStem和SnowballStemmer后的结果是单个字符向量。这导致函数DocumentTermMatrix无法再次处理语料库。有什么办法可以解决这个问题吗? - Christian
@Christian 我为此编辑了我的答案。如果有更简单的方法,我不知道。 - Apprentice Queue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接