在Python或R中计算词频

0 投票
5 回答
1657 浏览
提问于 2025-04-17 23:16

根据下面Tyler的评论,我对问题进行了编辑。

在一个更大的文本挖掘项目中,我创建了一个.csv文件,第一列是书名,第二列是书的全部内容。我的目标是为每个书名创建一个词云,这个词云包含文本中最常出现的前n个(n可以是100、200或1000,具体取决于得分的分布情况)单词,同时去掉常见的英语停用词(R的tm包有一个很好的功能可以做到这一点,叫做removeStopwords)。希望这样能更好地解释我的问题。

问题描述:

我的输入格式如下,存储在一个csv文件中:

title   text
1   <huge amount of text1>
2   <huge amount of text2>
3   <huge amount of text3>

这里有一个类似数据的最小工作示例:

library(tm)
data(acq)
dat <- data.frame(title=names(acq[1:3]), text=unlist(acq[1:3]), row.names=NULL)

我想找出每个书名对应文本中按频率出现的前"n"个词,排除停用词。理想的输出是一个Excel或csv表格,格式如下:

title   term    frequency
1       ..       ..
1       ..       ..
1       
1       
1       
2       
2       
2       
2       
2       
3       
3       
3       ..      ..

请指导一下,这个可以用R或Python实现吗?有谁能帮忙吗?

5 个回答

0

这段话的意思是,你可以按照自己的需求来操作:

library(qdap)
list_df2df(setNames(lapply(dat$text, freq_terms, top=10, 
    stopwords = Dolch), dat$title), "Title")

你可以去掉一些常见的无意义词(比如“的”、“是”等),然后用 freq_terms 来找出每段文本中最常出现的前 n 个词。接着,你可以给这些词起名字,并用 list_df2df 把它们整合在一起。

在这里,我使用了 qdapDictionaries:Dolch 这个列表来作为无意义词的参考,你也可以用其他的词汇表。此外,如果有多个词在前十名中并列,那么这些词都会被包含在内。

##              Title           WORD FREQ
## 1   reut-00001.xml       computer    6
## 2   reut-00001.xml        company    4
## 3   reut-00001.xml           dlrs    4
## .
## .
## .
## .
## 112 reut-00003.xml        various    1
## 113 reut-00003.xml           week    1
## 114 reut-00003.xml         within    1
0

在R语言中:

dat <- read.csv("myFile")
splitPerRow <- strsplit(dat$text, "\\W")
tablePerRow <- lapply(splitPerRow, table)
tablePerRow <- lapply(tablePerRow, sort, TRUE)
tablePerRow <- lapply(tablePerRow, head, n) # set n to be the threshold on frequency rank

output <- data.frame(freq=unlist(tablePerRow),
                     title=rep(dat$title, times=sapply(tablePerRow, length))
                     term = unlist(lapply(tablePerRow, names))
                      )

根据文本的不同情况,你可能需要过滤掉一些不是单词的内容。比如,如果文本是“term1 term2, term3”,那么在逗号和term2后面的空格之间会产生一个空的条目,这个空条目就是因为有一个空字符串造成的。

0

在基础R语言中:


## set up some data
words <- paste(LETTERS[1:3], letters[1:3], sep = "")
dat <- data.frame(title = 1:3, text = sapply(1:3, function(x){
  paste(sample(unlist(strsplit(words, " ")), 15, TRUE), collapse = " ")
  }))
dat$text <- as.character(dat$text)

## solve the problem
> tabs <- sapply(dat$text, function(x){
    table(unlist(strsplit(x, " ")))
    }, USE.NAMES = FALSE)
> data.frame(title = sort(rep(1:nrow(dat), 3)), 
             text = sort(rep(rownames(tabs))), 
             freq = c(tabs))

## title text freq
##     1   Aa    6
##     1   Bb    3
##     1   Cc    6
##     2   Aa    9
##     2   Bb    4
##     2   Cc    2
##     3   Aa    4
##     3   Bb    7
##     3   Cc    4
0

在R语言中,你可以使用 stringi 这个包,还有 stri_extract_all_charclass 这个函数来从文本中提取所有的字母:

 stri_extract_all_charclass(c("Ala ma; kota. Jaś nie ma go\n.To nic nie ma 123","abc dce"),"\\p{Lc}")
## [[1]]
## [1] "Ala"  "ma"   "kota" "Jaś"  "nie"  "ma"   "go"   "To"   "nic"  "nie"  "ma"  
## 
## [[2]]
## [1] "abc" "dce"

然后,你可以用 table 函数来统计这些单词的数量。你可能还想把每个单词都变成小写,这时候可以用 stri_trans_tolower 这个函数。

stri_extract_all_charclass(c("Ala ma; kota. Jaś nie ma go\n.To nic nie ma 123","abc dce"),"\\p{Lc}") -> temp
lapply(temp, table)
## [[1]]
## 
##  Ala   go  Jaś kota   ma  nic  nie   To 
##    1    1    1    1    3    1    2    1 

## [[2]]

## abc dce 
##   1   1 
3

在Python中,你可以使用来自collections模块的Counter,再加上re来把句子按每个单词分开,这样你就能得到这个结果:

>>> import re
>>> from collections import Counter
>>> t = "This is a sentence with many words. Some words are repeated"
>>> Counter(re.split(r'\W', t)).most_common()
[('words', 2), ('a', 1), ('', 1), ('sentence', 1), ('This', 1), ('many', 1), ('is', 1), ('Some', 1), ('repeated', 1), ('are', 1), ('with', 1)]

撰写回答