1.情感数据集
如上所述,存在多种用于评估文本中的观点或情感的方法和字典。
tidytext
包提供了对几个情感词典的访问。三个通用词典是:
- AFINN
- bing
- nrc
所有这三个词典都基于一元词组(
unigram
),即单个单词。这些词典包含许多英语单词,并且这些单词被分配了正面/负面情绪的分数,也可能是喜悦、愤怒、悲伤等情绪。 nrc 词典以二进制方式(“是”/“否”)将单词分类为积极、消极、愤怒、预期、厌恶、恐惧、快乐、悲伤、惊讶和信任的类别。bing词典以二进制方式将单词分为正面和负面类别。 AFINN 词典为单词分配一个介于 -5 和 5 之间的分数,负分表示负面情绪,正分表示正面情绪。在下载数据之前,我们可能会被要求同意许可。如果在jupyter-notebook里面运行的话会失败,建议大家在rstudio里面先运行下载。
函数 get_sentiments() 允许我们获取特定的情感词典,并为每个词典提供适当的度量。我们现在来看一下各个情绪词典的信息
library(`tidytext`)
library(dplyr)
get_sentiments("nrc") %>% head()
A tibble: 6 × 2
word | sentiment |
abacus | trust |
abandon | fear |
abandon | negative |
abandon | sadness |
abandoned | anger |
abandoned | fear |
get_sentiments("bing") %>% head()
A tibble: 6 × 2
word | sentiment |
2-faces | negative |
abnormal | negative |
abolish | negative |
abominable | negative |
abominably | negative |
abominate | negative |
get_sentiments("afinn") %>% head()
A tibble: 6 × 2
word | value |
abandon | -2 |
abandoned | -2 |
abandons | -2 |
abducted | -2 |
abduction | -2 |
abductions | -2 |
这些词典都是通过整合云资源、餐厅或电影评论等数据的某种组合进行验证。鉴于这些信息,我们可能会犹豫将这些情感词典应用于与它们所验证的文本风格截然不同的文本风格,例如 200 年前的叙事小说,虽然可能这些情感词典来分析之前作家的小说可能不完全准确,但为了方便分析,这里我们还是使用这些词典来进行情感分析.还有一些特定领域的情感词典可用,用于分析来自特定内容领域的文本。后续我们会探讨使用用于金融的情绪词典的分析。
我们通过基于字典的方法通过将文本中每个单词的单独情绪分数相加来找到一段文本的总情绪。
但是并非每个英语单词都在词典中,因为许多英语单词都是相当中性的。重要的是要记住,这些方法不考虑单词前的限定词,例如“no good”或“not true”;像这样的基于词典的方法仅基于 unigrams。如果要根据上下文分析的话,我们需要使用语言模型来解决,这在后续将进行相关介绍。需要注意的是:我们使用累加 unigram 情绪分数的方法可能会受到文本块的大小的影响。 当大段落的文本通常可以具有平均为零的正面和负面情绪,而向几句话句子大小或段落大小的文本通常效果更好。
2.使用内连接进行情感分析
使用
tidydata
格式的数据,可以将情感分析作为内连接来完成。这是将文本挖掘视为一项整洁的数据分析任务的又一巨大成功;就像删除停用词是一种反连接操作一样,执行情感分析是一种内连接操作。让我们看一下 NRC 词典中带有joy的单词。Emma中最常见的快乐词是什么?首先,我们需要获取小说的文本,并使用 unnest_tokens() 将文本转换为整洁的格式,就像我们在上一篇文章中所做的那样。让我们还设置一些其他列来跟踪每个单词来自书的哪一行和哪一章;我们使用 group_by 和 mutate 来构造这些列。具体代码如下:
library(janeaustenr)
library(dplyr)
library(stringr)
tidy_books <- austen_books() %>%
group_by(book) %>%
mutate(
linenumber = row_number(),
chapter = cumsum(str_detect(text,
regex("^chapter [\\divxlc]",
ignore_case = TrUE)))) %>%#使用正则表达式来定义章节
ungroup() %>%
unnest_tokens(word, text)#分词
tidy_books %>% head()
A tibble: 6 × 4
book | linenumber | chapter | word |
Sense & Sensibility | 1 | 0 | sense |
Sense & Sensibility | 1 | 0 | and |
Sense & Sensibility | 1 | 0 | sensibility |
Sense & Sensibility | 3 | 0 | by |
Sense & Sensibility | 3 | 0 | jane |
Sense & Sensibility | 3 | 0 | austen |
注意,我们从 unnest_tokens() 中为输出列选择了名称 word。这是一个方便的选择,因为情感词典和停用词数据集都有名为 word 的列;执行内部连接和反连接因此更容易。
现在文本的格式很整洁,每行一个单词,我们准备好进行情绪分析了。首先,让我们使用 NRC 词典和 filter() 来表示快乐的词。接下来,让我们使用filter来筛选来自 Emma 的单词,然后使用 inner_join() 执行情绪分析。艾玛中最常见的joy
是什么?让我们使用 dplyr 中的 count()。
nrc_joy <- get_sentiments("nrc") %>%
filter(sentiment == "joy")
tidy_books %>%
filter(book=='Emma') %>%
inner_join(nrc_joy) %>%
count(word,sort=TrUE)%>%
head()
A tibble: 6 × 2
word | n |
good | 359 |
friend | 166 |
hope | 143 |
happy | 125 |
love | 117 |
deal | 92 |
我们在这里看到的大多是关于
friend
和love
的积极、快乐的话语。我们还可以检查每部小说的情绪如何变化。我们只需几行主要是 dplyr 函数就可以做到这一点。首先,我们使用 Bing 词典和 inner_join() 找到每个单词的情感分数。
接下来,我们计算每本书的某些位置有多少积极和消极的词。这样我们可以分析情绪的变化情况。我们在这里定义一个索引来跟踪我们在叙述中的位置;该索引(使用整数除法)对 80 行文本的部分进行计数。
一小段文本可能没有足够的单词来很好地估计情绪,但对于太大的文本可能会导致正负情绪抵消。对于这些书,使用80行效果很好,但这可能会因单个文本、行的开头长度等而有所不同。然后我们使用 pivot_wider() 以便我们在不同的列中拥有消极和积极的情绪,最后计算净情绪(正面 - 负面)。
library(tidyr)
jane_austen_sentiment <- tidy_books %>%
inner_join(get_sentiments("bing")) %>%#使用bing情绪词典进行内连接
count(book, index = linenumber %/% 80, sentiment) %>%#按八十行为一个小段进行记数
pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) %>%#将数据转换成宽数据
mutate(sentiment = positive - negative)#计算净情绪,如果大于0说明是积极情绪,小于0说明是消极的
jane_austen_sentiment %>% head()
A tibble: 6 × 5
book | index | negative | positive | sentiment |
Sense & Sensibility | 0 | 16 | 32 | 16 |
Sense & Sensibility | 1 | 19 | 53 | 34 |
Sense & Sensibility | 2 | 12 | 31 | 19 |
Sense & Sensibility | 3 | 15 | 31 | 16 |
Sense & Sensibility | 4 | 16 | 34 | 18 |
Sense & Sensibility | 5 | 16 | 51 | 35 |
现在我们可以在每部小说的情节轨迹上绘制这些情绪分数。请注意,我们绘制在x轴上的索引,是对应的小段文本,即每隔八十行为一段,这也反应了每本书的时间情绪变化
library(ggplot2)
ggplot(jane_austen_sentiment, aes(index, sentiment, fill = book)) +
geom_col()+#绘制柱形图
facet_wrap(~book, ncol = 2, scales = "free\_x")#根据不同书进行分面绘图,两行
我们可以在上图中看到,每部小说故事情节的情绪变化
3.对比三种情感字典
如何选用不同的情绪词典,我们可能需要更多信息,了解哪一个适合我们研究的目的。现在我们使用三个不同的情感词典,并分析情感在《傲慢与偏见》中是如何变化的。 首先,让我们使用 filter() 从我们感兴趣的一本小说中选择单词。代码如下:
pride_prejudice <- tidy_books %>%
filter(book == 'Pride & Prejudice')
pride_prejudice %>% head()
A tibble: 6 × 4
book | linenumber | chapter | word |
Pride & Prejudice | 1 | 0 | pride |
Pride & Prejudice | 1 | 0 | and |
Pride & Prejudice | 1 | 0 | prejudice |
Pride & Prejudice | 3 | 0 | by |
Pride & Prejudice | 3 | 0 | jane |
Pride & Prejudice | 3 | 0 | austen |
我们现在可以使用inner_join()计算不同形式的情感
注意:AFINN词典是通过-5—+5来衡量情感的。而其他两个词典以二进制方式对情感单词进行分类。
# 使用AFINN词典
afinn <- pride_prejudice %>%
inner_join(get_sentiments("afinn")) %>% #内连接,得到带有情感的文本
group_by(index = linenumber %/% 80) %>% #每隔80行作为一小段
summarise(sentiment = sum(value)) %>% #这里我们进行一个求和处理,因为这里是以数字表示情感的
mutate(method = "AFINN")
# bing词典
bing <- pride_prejudice %>%
inner_join(get_sentiments("bing")) %>%#使用bing词典进行内连接
mutate(method = "Bing")%>%
count(index = linenumber %/% 80, sentiment) %>%
pivot_wider(names_from = sentiment,
values_from = n,
values_fill = 0) %>%
mutate(sentiment = positive - negative)
# 使用nrc词典
nrc <- pride_prejudice %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment %in% c('positive','negative'))) %>%
mutate(method = "NRC")%>%
count(index = linenumber %/% 80, sentiment) %>%
pivot_wider(names_from = sentiment,
values_from = n,
values_fill = 0) %>%
mutate(sentiment = positive - negative)
现在我们比较使用三个不同词典的结果进行可视化分析
bind_rows(afinn,
bing_and_nrc) %>%
ggplot(aes(index, sentiment, fill = method)) +
geom_col(show.legend = FALSE) +
facet_wrap(~method, ncol = 1, scales = "free\_y")
用于情感分析的三个不同词典给出的结果在绝对意义上是不同的,但在小说情节中具有相似的相对轨迹。我们在小说中几乎相同的地方看到了类似的情绪低谷和高峰,但绝对值明显不同。
- AFINN词典给出了最大的绝对值,具有较高的正值。
- Bing 等的词典。具有较低的绝对值,并且似乎标记了较大的连续正面或负面文本块。
- NRC结果相对于其他两个词典,更积极地标记文本。
在查看其他小说时,我们发现这些方法之间存在类似的差异; NRC更偏向给予积极的情绪,AFINN 情绪有更多变化,Bing的情绪似乎会找到更长的相似文本,但三个词典都大致情绪的整体趋势。
例如,与 Bing等词典相比,为什么 NRC 词典的结果在情感上的偏差如此之大。让我们简要地看一下这些词典中有多少积极和消极的词。