在Python或R中计算词频
根据下面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 个回答
这段话的意思是,你可以按照自己的需求来操作:
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
在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后面的空格之间会产生一个空的条目,这个空条目就是因为有一个空字符串造成的。
在基础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
在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
在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)]