数据科学20:文本挖掘2

数据科学20:文本挖掘2

Jun 26th, 2014

数据科学20:文本挖掘2_第1张图片

图片由本文中数据生产~

“文章原创,转载请注明出处”

一、对词条-文档矩阵的操作

在’tm’包中,提供了一些常用的函数,可以对得到的Document Term Matrix进行一些操作。当然,我们也可以使用自己的方式,对该矩阵进行一些探索,比如,我们先来看看词条的频数:

1.1 词条频数

1
2
3
4
freq <- colSums(as.matrix(dtm)) length(freq)  ## [1] 780 

如果我们想看看,哪些频数是大于等于30的,我们可以:

1
2
3
names(freq[freq >= 30])  ## [1] "market" "mln" "oil" "opec" "price" "said" 

但其实,在’tm’包中有自带的函数可以解决:

1
2
3
findFreqTerms(dtm, lowfreq = 30)  ## [1] "market" "mln" "oil" "opec" "price" "said" 

如果得到了每个词条的频数,我们可以列一个表查看一些其它的东西:

1
2
3
4
5
6
7
8
9
10
11
12
13
ord <- order(freq, decreasing = TRUE) ## 查看频数排在前十的词条及其频数 head(freq[ord], 10)  ## oil said price opec mln market barrel last bpd dlrs ## 86 73 63 47 31 30 26 24 23 23  ## 查看频数的频数 tail(table(freq), 10)  ## freq ## 21 23 24 26 30 31 47 63 73 86 ## 2 2 1 1 1 1 1 1 1 1 

1.2 相关性

除了词条的频数,我们大都还会对词条之间的相关性感兴趣。如何计算,其实很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
corr <- cor(as.matrix(dtm)) corr[1:5, 1:5]  ## abdul abil abl abroad accept ## abdul 1.00000 -0.08812 -0.05263 -0.05263 -0.05263 ## abil -0.08812 1.00000 -0.08812 0.79309 -0.08812 ## abl -0.05263 -0.08812 1.00000 -0.05263 -0.05263 ## abroad -0.05263 0.79309 -0.05263 1.00000 -0.05263 ## accept -0.05263 -0.08812 -0.05263 -0.05263 1.00000  dim(corr)  ## [1] 780 780 

比如我们想知道,与词条’oil’相关性超过0.8的词条有哪些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
op <- options() options(digits = 2) name <- setdiff(names(corr[, "oil"][corr[, "oil"] > 0.8]), "oil") value <- corr[name, "oil"] matrix <- matrix(value[order(value, decreasing = TRUE)]) rownames(matrix) = names(value) colnames(matrix) = "oil" matrix  ## oil ## name 0.87 ## opec 0.81 ## tri 0.81 ## want 0.81  options(op) 

但其实,’tm’包中提供了现成函数:

1
2
3
4
5
6
7
findAssocs(dtm, "oil", 0.8)  ## oil ## opec 0.87 ## name 0.81 ## tri 0.81 ## want 0.81 

可以看到,这一个函数实现了上面我们那一长串的功能。但是,我觉得,提供的现成函数有好处,但还是需要自己想想如何实现这个现成的函数。这不仅对概念理解有帮助,也对程序编写以及了解别人写的函数有更加深刻的理解。

1.3 删减稀疏条目

大部分时候,Document Term Matrix是一个很大的矩阵,而且是行数远小于列数。也就是说,这个矩阵实际上是很稀疏的,不妨来看看我们这个只有20个文档的矩阵,稀疏程度如何:

1
2
3
4
5
6
7
8
9
10
11
12
13
Sparse <- length(which(matrix(dtm) == 0)) Sparse  ## [1] 14030  Non <- length(which(matrix(dtm) != 0)) Non  ## [1] 1570  sprintf("%d%%", round(Sparse/(Non + Sparse), 2) * 100)  ## [1] "90%" 

可以看到,矩阵中等于零的数目是14030,不为零的为1570,稀疏程度达到了90%,显然是非常稀疏的。当然,其实这个可以不用自己算的:

1
2
3
4
5
6
7
dtm  ## <<DocumentTermMatrix (documents: 20, terms: 780)>> ## Non-/sparse entries: 1570/14030 ## Sparsity : 90% ## Maximal term length: 13 ## Weighting : term frequency (tf) 

上面的输出,前两个就知道它的意思了。那么另外两个呢?“Maximal term length”,顾名思义,就是最长的那个词条的长度。不妨来看一下:

1
2
3
4
5
6
7
8
name <- colnames(as.matrix(dtm)) name.length <- sapply(name, nchar) max.name <- name[name.length == max(name.length)] max.value <- name.length[max.name] max.value  ## responsibilit ## 13 

可以看到是吻合的。至于最后一个“Weighting”,是指Document Term Matrix中的每一条目的值是如何计算的。这里用的是“term frequency”,就是词条频率,简写为“tf”。除了这个,还有一些其它计算方法,比如:tf-idf,即term frequency-inverse document frequency。这个以后再说。

回到主题:计算出了稀疏条目的比例,证实了矩阵的确是很稀疏的,那么下面就是要去删除一些条目。有些条目在很少的文档中出现,甚至只在一篇文档中出现了。一般来说,删除这样的条目不会对矩阵的信息继承带来显著的影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
remove.sparseterms <- function(dtm, per) {  dtm.Matrix <- as.matrix(dtm)  term.per <- apply(dtm.Matrix, 2, function(item) length(which(item == 0))/length(item))  name <- names(term.per[which(term.per < per)])  return(dtm.Matrix[, name]) } remove.sparseterms(dtm, 0.4)  ## Terms ## Docs barrel oil one price reuter said ## 127 2 5 0 5 1 3 ## 144 0 12 1 6 2 11 ## 191 1 2 0 2 1 1 ## 194 1 1 1 2 1 1 ## 211 0 1 0 0 1 3 ## 236 4 7 1 8 1 10 ## 237 0 4 1 1 1 1 ## 242 0 3 2 2 1 3 ## 246 1 5 1 2 1 5 ## 248 3 9 1 10 1 7 ## 273 3 5 1 5 1 8 ## 349 0 4 0 1 1 1 ## 352 1 5 0 5 1 2 ## 353 1 4 1 2 1 1 ## 368 0 3 0 0 1 3 ## 489 3 4 2 3 1 2 ## 502 3 5 2 3 1 2 ## 543 1 3 1 3 1 4 ## 704 0 3 4 3 1 4 ## 708 2 1 0 0 1 1 

这边的计算就是:检查词条的稀疏程度是否低于给定的系数per,如果是,就保留该词条;如果不是,则舍弃。

当然,在’tm’包中也有自带的函数可以解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
rsterms <- removeSparseTerms(dtm, 0.4) inspect(rsterms)  ## <<DocumentTermMatrix (documents: 20, terms: 6)>> ## Non-/sparse entries: 103/17 ## Sparsity : 14% ## Maximal term length: 6 ## Weighting : term frequency (tf) ## ## Terms ## Docs barrel oil one price reuter said ## 127 2 5 0 5 1 3 ## 144 0 12 1 6 2 11 ## 191 1 2 0 2 1 1 ## 194 1 1 1 2 1 1 ## 211 0 1 0 0 1 3 ## 236 4 7 1 8 1 10 ## 237 0 4 1 1 1 1 ## 242 0 3 2 2 1 3 ## 246 1 5 1 2 1 5 ## 248 3 9 1 10 1 7 ## 273 3 5 1 5 1 8 ## 349 0 4 0 1 1 1 ## 352 1 5 0 5 1 2 ## 353 1 4 1 2 1 1 ## 368 0 3 0 0 1 3 ## 489 3 4 2 3 1 2 ## 502 3 5 2 3 1 2 ## 543 1 3 1 3 1 4 ## 704 0 3 4 3 1 4 ## 708 2 1 0 0 1 1 

与之前的结果相同。

二、相关的绘图

介绍完Document Term Matrix之后,其实已经可以开始使用模型去处理了。之前介绍过聚类、分类啊等等的内容,有了这个矩阵之后,其实都可以去做了。不过,在建立模型之前,我想先说说有关绘图的问题。

我们前面算了很多的量,比如频数啊、相关系数啊等等。但其实,我们大多时候需要用图形将它们展示出来。在R中,我们可以使用Rgraphviz包来绘制词条之间的关系图:

1
2
require(Rgraphviz) plot(dtm, terms = findFreqTerms(dtm, lowfreq = 20)) 

数据科学20:文本挖掘2_第2张图片

1
2
## 指定相关性必须在0.5之上才可连线 plot(dtm, terms = findFreqTerms(dtm, lowfreq = 20), corThreshold = 0.5) 

数据科学20:文本挖掘2_第3张图片

在默认不指定termscorThreshold参数的情况下,plot函数会绘制随机20个词条,相关性至少0.7的图形。

当然,我们还可以绘制熟悉的频数直方图:

1
2
3
4
5
6
freq <- sort(colSums(as.matrix(dtm)), decreasing = TRUE) tf <- data.frame(term = names(freq), freq = freq)  g <- ggplot(subset(tf, freq > 20), aes(term, freq)) g <- g + geom_bar(stat = "identity", aes(fill = freq)) print(g) 

数据科学20:文本挖掘2_第4张图片

另外一个比较流行好看的图,应该就是文本云(wordcloud)了,可以使用wordcloud包实现:

1
2
require(wordcloud) wordcloud(names(freq), freq, min.freq = 5, max.words = 80) 

数据科学20:文本挖掘2_第5张图片

1
2
3
4
## 添加颜色 require(RColorBrewer) wordcloud(names(freq), freq, min.freq = 5, max.words = 80, colors = brewer.pal(8,  "Paired")) 

数据科学20:文本挖掘2_第6张图片

当然,wordcloud()函数提供了很多选项,可以自行查看,我就不多讲了。

 Jun 26th, 2014 DataScience, TextMining

转自:http://jackycode.github.io/blog/2014/06/26/text-mining2/

你可能感兴趣的:(数据,大数据,机器学习,文本)