【问题标题】:Snowball Stemmer only stems last wordSnowball Stemmer 只提取最后一个词
【发布时间】:2023-03-11 05:49:01
【问题描述】:

我想使用 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 不是 Snowball 的 R 接口吗?因此,您应该使用 library(Rstem) 并尝试 tm_map(corp, wordStem)。
  • 感谢您的评论。我试过了,结果是一样的。我将在上面添加一个更好的示例来进一步说明问题。

标签: r stemming tm


【解决方案1】:

加载所需的库

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 个库中的函数来解决您的问题的简化解决方案。

【讨论】:

    【解决方案2】:

    我看到的问题是 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 我为此编辑了答案。如果有更简单的方法,我不知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 2021-07-10
    相关资源
    最近更新 更多