logo

第 10 章 文本挖掘

作者
Modified on
Reading time
10 分钟阅读:..评论:..

随着互联网的飞速发展,人们每天都会产生大量的文本数据,如新闻报道、博客文章、社交媒体评论等。这些非结构化的文本数据蕴含着丰富的信息,通过文本挖掘技术,我们可以从海量文本数据中发现有价值的知识和见解。 本章将介绍如何使用 R 语言进行文本挖掘和分析。我们将学习文本数据的获取与处理、文本分析与可视化、文本分类与聚类等内容,并通过一个实际案例来演示如何进行情感分析。

10.1 文本数据的获取与处理

在进行文本挖掘之前,我们需要先获取文本数据,并对其进行预处理。

10.1.1 获取文本数据

可以通过多种途径获取文本数据,例如:

  • 网页抓取:使用 rvest 等 R 包从网页中抓取文本内容
  • 读取本地文件:使用 readLines、read.table 等函数读取 txt、csv 等本地文件
  • 连接数据库:使用 RMySQL、RSQLite 等包连接数据库获取文本字段
  • 调用 API 接口:很多平台如 Twitter 都提供了 API 接口,方便获取文本数据

下面是一个使用 rvest 包从网页中抓取新闻标题的示例:

library(rvest) url <- "http://news.sina.com.cn/china/" web <- read_html(url) titles <- web %>% html_nodes("a") %>% html_text() head(titles)

10.1.2 文本预处理

获取到原始文本数据后,需要进行一系列预处理,将非结构化的文本转换为结构化、规范化的形式,为后续分析奠定基础。主要的预处理步骤包括:

  • 分词:将句子切分成单词。中文可使用 jiebaR 包,英文可使用 stringr 包等
  • 去除停用词:删除如"的"、"是"等对分析无意义的高频虚词
  • 词干提取:将"学习"、"学习者"还原为同一词干"学"。英文 stemDocument 函数
  • 转小写:将所有字母转为小写,忽略大小写差异

以下是一个利用 jiebaR 包和停用词表对中文文本进行预处理的例子:

library(jiebaR) library(dplyr) # 准备文本和停用词 text <- c("今天天气真好,我们一起去公园玩吧!","不行啊,我今天有很多作业要做。") stopwords <- c("啊","吧","的") # 分词 words <- worker() %>% segment(text,type = "tag") # 去除停用词,转换为语料格式 corpus <- words[-which(words %in% stopwords)] %>% table() %>% as.data.frame()

10.1.3 词云图生成

词云图是一种直观展示文本中高频词的可视化方式。在 R 中可以用 wordcloud2 等包来轻松生成美观的词云图。

library(wordcloud2) wordcloud2(corpus, size = 0.5, minSize = 1, gridSize = 1, fontFamily = 'Segoe UI', color = 'random-light', backgroundColor = "white", minRotation = -pi/4, maxRotation = pi/4, rotateRatio = 0.8)

通过词云图,我们可以直观看出文本数据中出现频率较高的词,快速把握文本的主题和关键信息。

10.2 文本分析与可视化

对文本数据进行适当的量化分析和可视化展示,能帮助我们更好地理解和挖掘文本信息。

10.2.1 词频分析

词频反映了一个词在文本中出现的频率,是最基本的文本统计方式。 首先,我们需要构建语料库,将多个文本文档组织为语料的格式。tm 包提供了强大的语料处理功能。

library(tm) text <- c("Text mining is fun.", "R is a great tool for text mining.") corpus <- Corpus(VectorSource(text)) # 语料预处理 corpus <- tm_map(corpus, tolower) corpus <- tm_map(corpus, removePunctuation) corpus <- tm_map(corpus, removeWords, stopwords("english")) # 构建词频矩阵 dtm <- DocumentTermMatrix(corpus) freq <- colSums(as.matrix(dtm)) freq_df <- data.frame(word=names(freq), freq=freq)

然后使用 ggplot2 等包对词频进行可视化:

library(ggplot2) ggplot(freq_df, aes(x=word, y=freq)) + geom_bar(stat="identity", fill="skyblue") + coord_flip() + theme_minimal()

10.2.2 共现分析

共现分析用于揭示文本中词语之间的关联关系,寻找在文本中经常一起出现的词。 我们可以用 widyr 包计算词语共现频率,并用 igraph 包进行可视化。

library(widyr) library(igraph) # 提取词对 word_pairs <- corpus %>% unnest_tokens(paired_words, text, token = "ngrams", n = 2) # 统计词对共现频率 pair_freq <- word_pairs %>% count(paired_words, sort = TRUE) # 筛选高频词对 top_pairs <- pair_freq %>% filter(n >= 2) %>% separate(paired_words, c("word1", "word2"), sep = " ") # 可视化共现网络 graph <- graph_from_data_frame(top_pairs) plot(graph, vertex.size=5, vertex.label.cex=0.7, edge.curved=0.2)

通过共现网络图,我们可以看出哪些词经常在一起出现,它们在语义上可能有一定的关联。

10.2.3 文本聚类

文本聚类可以发现文本数据内在的分组结构,将相似的文本自动归类到一起。 常见的文本聚类方法有基于 VSM 的 k-means 聚类,以及主题模型如 LDA。下面演示 k-means 聚类的过程。

library(topicmodels) # 构建TF-IDF矩阵 dtm_tfidf <- DocumentTermMatrix(corpus, control = list(weighting = weightTfIdf)) # 转换为数值矩阵 m <- as.matrix(dtm_tfidf) # 进行k-means聚类 cl <- kmeans(m, 2) # 聚类结果可视化 plot(m, col = cl$cluster) points(cl$centers, col = 1:2, pch = 8, cex=2)

利用聚类,我们可以自动将大规模文本语料划分为不同的主题类别,便于后续针对性分析。

10.3 文本分类与情感分析

文本分类和情感分析是文本挖掘的两大常见任务,前者侧重判别文本的类别,后者侧重判别文本的情感倾向。

10.3.1 文本分类

文本分类就是根据文本内容将其划分到预定义的类别中,如将邮件分为垃圾邮件和正常邮件。 我们以新闻分类为例。首先准备好训练数据:

library(quanteda) library(caret) news <- data.frame( text = c("福布斯:姚明当选名人堂是因为他改变了篮球","美军内部报告揭露驻日美军的腐败和黑幕","今年前4月中国进出口总值7.67万亿","寻找另一个自己:你在另一个平行宇宙过着什么样的生活?"), type = c("sports","military", "finance","science") ) # 语料预处理 news_corpus <- corpus(news$text) news_dfm <- dfm(news_corpus, stem = TRUE, remove = stopwords("chinese"))

然后进行分类器训练和预测:

# 转换为文档-词频矩阵 news_df <- convert(news_dfm, to = "data.frame") colnames(news_df) <- make.names(colnames(news_df)) # 添加目标分类列 news_df$type <- news$type # 划分训练集和测试集 set.seed(123) trainIndex <- createDataPartition(news_df$type, p = 0.8, list = FALSE) train <- news_df[trainIndex,] test <- news_df[-trainIndex,] # 训练分类器 model <- train(type ~ ., data = train, method = "rf") # 在测试集上预测 pred <- predict(model, newdata = test) confusionMatrix(pred, test$type)

我们使用了随机森林(rf)作为分类算法,训练出的模型在测试集上可以准确预测新闻类别。通过不断优化特征和模型,可以构建高精度的文本分类器。

10.3.2 情感分析

情感分析就是判断一段文本所包含的情感倾向,是积极、消极还是中性的。 以下是利用 SnowNLP 包对酒店评论进行情感判断的示例:

library(SnowNLP) review1 <- "酒店环境不错,房间很干净,服务人员态度很好。" review2 <- "房间隔音效果差,晚上吵的根本睡不着。" s1 <- SnowNLP(review1) s1[1] paste("情感倾向:", s1$sentiment) s2 <- SnowNLP(review2) s2[1] paste("情感倾向:", s2$sentiment)
[1] "酒店环境不错,房间很干净,服务人员态度很好。" [1] "情感倾向: 0.991765925639926" [1] "房间隔音效果差,晚上吵的根本睡不着。" [1] "情感倾向: 0.133741866897081"

可以看到,SnowNLP 包可以较准确地判断出第一条评论为积极情感,第二条为消极情感。我们可以批量应用情感分析,监测网络舆情动向。

10.4 实践案例:豆瓣电影评论情感分析

下面我们通过一个实际案例--豆瓣电影评论情感分析,来综合运用本章学到的知识。 分析思路如下:

  • 抓取豆瓣电影《肖申克的救赎》的短评内容
  • 对评论内容进行分词、去停用词等预处理
  • 提取关键词,生成词云
  • 使用 SnowNLP 判断每条评论的情感倾向
  • 统计并可视化整体情感分布

10.4.1 抓取豆瓣影评数据

library(rvest) library(stringr) # 抓取前10页评论 all_comments <- c() for (i in 1:10) { url <- str_c("https://movie.douban.com/subject/1292052/comments?start=", (i-1)*20, "&limit=20&status=P") web <- read_html(url) comments <- web %>% html_nodes("span.short") %>% html_text() all_comments <- c(all_comments, comments) Sys.sleep(rnorm(1,1,0.2)) } # 保存为本地文件 write.table(all_comments, "comments.csv", sep="\t", row.names=FALSE, fileEncoding="UTF-8")

10.4.2 文本预处理

library(jiebaR) # 读取评论数据 comments <- read.csv("comments.csv", header=FALSE, sep="\t", stringsAsFactors=FALSE, fileEncoding="UTF-8") # 定义停用词 stopwords <- c("就是","可以","所以","但是","还是","只是","真的") # 分词和去停用词 comments$words <- sapply(comments$V1, function(x) { words <- worker() %>% segment(x, type = "tag") paste(words[-which(words %in% stopwords)], collapse=" ") })

10.4.3 提取关键词,并绘制词云图

library(wordcloud2) # 统计高频词 word_freq <- comments$words %>% strsplit(" ") %>% unlist() %>% table()好的,我将继续为你输出第10章剩余的内容: ```r # 选取频率最高的50个词绘制词云 wordcloud2(head(sort(word_freq, decreasing=TRUE), 50), size = 0.5, minSize = 1, gridSize = 1, fontFamily = 'Segoe UI', color = 'random-light', backgroundColor = "white", minRotation = -pi/4, maxRotation = pi/4, rotateRatio = 0.8)

从词云图可以看出,"希望"、"自由"、"信念"等是《肖申克的救赎》影评中的高频词,反映了影片所传递的主题。

10.4.4 情感倾向分析

接下来,我们使用 SnowNLP 对每条评论进行情感判断,并统计整体的情感分布:

library(SnowNLP) # 定义情感分析函数 sentiment_score <- function(text) { s <- SnowNLP(text) return(s$sentiment) } # 计算每条评论的情感得分 comments$sentiment <- sapply(comments$V1, sentiment_score) # 查看情感得分分布 hist(comments$sentiment, main="情感分布图", xlab="情感得分")

从情感分布图可以看出,绝大部分影评的情感得分都在 0.5 以上,整体情感非常正面,说明《肖申克的救赎》这部电影得到了大多数观众的认可和好评。 通过这个实践案例,我们运用爬虫抓取了豆瓣电影的评论数据,并对其进行了分词、关键词提取、情感分析等文本挖掘任务,从大量非结构化的文本数据中挖掘出了有价值的信息和见解。

本章小结

本章我们系统学习了如何使用 R 语言进行文本挖掘与分析。具体内容包括:

  • 文本数据的获取与处理,如抓取网页文本、读取本地文件、分词去停用词等
  • 文本分析与可视化,如词频统计、共现分析、文本聚类等
  • 文本分类与情感分析的基本原理和实现
  • 一个实践案例,运用所学知识对豆瓣电影评论进行情感分析

文本挖掘是一个涉及语言学、统计学、计算机科学等多个领域的交叉学科。通过 R 语言及其丰富的包,我们可以较为轻松地上手文本挖掘。但要真正掌握文本挖掘,还需要扎实的自然语言处理和机器学习基础。 希望通过本章的学习,大家能够对文本挖掘的理论与实践有一个初步认识。在后续的学习和工作中,也要多多运用文本挖掘的思想,从文本大数据中发现有价值的商业智能和洞见。 【本章节完毕】