在 R 中进行情感分析
将词元与情感词典连接,以衡量正面或负面语气
在 R 中进行情感分析 是 CoddyKit 上的免费 R Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。
情感分析概述
情感分析为文本赋予情感倾向。tidytext 方法将单个单词与情感词典进行匹配,然后汇总分数。内置了三个情感词典:AFINN(数值分数)、Bing(正面/负面)和 NRC(情绪类别)。
library(tidytext)
# Available sentiment lexicons
# AFINN: -5 to +5 numeric score
# Bing: binary positive/negative
# NRC: emotion categories (joy, fear, anger, ...)
# Preview AFINN
afinn_sample <- get_sentiments('afinn')
cat('AFINN rows:', nrow(afinn_sample), '\n')
cat('Score range:', range(afinn_sample$value), '\n')
print(head(afinn_sample, 5))get_sentiments('afinn')
AFINN 词典为 2,477 个英语单词分配从 −5(非常负面)到 +5(非常正面)的整数分数。该词典由 Finn Årup Nielsen 编制,非常适合社交媒体和评论文本。
library(tidytext)
library(dplyr)
afinn <- get_sentiments('afinn')
# Most positive and most negative words
cat('Most positive words:\n')
print(afinn |> slice_max(value, n = 5))
cat('\nMost negative words:\n')
print(afinn |> slice_min(value, n = 5))
# Score distribution
cat('\nScore distribution:\n')
print(table(afinn$value))get_sentiments('bing')
Bing 词典(Bing Liu 等人)将 6,786 个单词分类为正面或负面。它比 AFINN 更大,适合产品评论和客户反馈等只需要简单情感倾向判断的场景。
library(tidytext)
library(dplyr)
bing <- get_sentiments('bing')
cat('Bing lexicon size:', nrow(bing), '\n')
cat('Positive words:', sum(bing$sentiment == 'positive'), '\n')
cat('Negative words:', sum(bing$sentiment == 'negative'), '\n')
# Sample positive and negative words
cat('\nSample positive:', head(bing$word[bing$sentiment == 'positive'], 8), '\n')
cat('Sample negative:', head(bing$word[bing$sentiment == 'negative'], 8), '\n')inner_join:为词语评分
inner_join(tokens, afinn, by = 'word')只保留出现在 AFINN 词典中的词元,并附加它们的评分。不在词典中的词会被静默丢弃——这既是优点(可以聚焦于已知的情感词),也是局限。
library(tidytext)
library(dplyr)
reviews <- tibble::tibble(
review_id = 1:3,
text = c(
'The product is excellent and outstanding quality',
'Terrible experience, broken and disappointing',
'Good value but slow delivery, acceptable overall'
)
)
scored <- reviews |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('afinn'), by = 'word')
cat('Scored words:\n')
print(scored[, c('review_id', 'word', 'value')])每篇文档的净情感
使用 group_by(document) |> summarise(sentiment = sum(value)) 汇总每篇文档的 AFINN 评分,以获得净情感分数。总和为正表示总体情感为正,总和为负表示情感为负。
library(tidytext)
library(dplyr)
reviews <- tibble::tibble(
review_id = 1:5,
text = c(
'excellent outstanding perfect love best amazing',
'terrible broken horrible awful waste money',
'good acceptable okay decent average',
'brilliant fantastic outstanding love recommend',
'poor bad disappointing slow useless'
)
)
net_sentiment <- reviews |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('afinn'), by = 'word') |>
group_by(review_id) |>
summarise(
sentiment = sum(value),
word_count = n()
) |>
mutate(polarity = ifelse(sentiment > 0, 'positive', 'negative'))
print(net_sentiment)Bing 情感:正面与负面计数
使用 Bing 词典,比较每篇文档中的正面词和负面词数量。计算 sentiment = positive_n - negative_n 得到净极性分数,或者将两种计数绘制为分组柱形图,以查看其构成。
library(tidytext)
library(dplyr)
corpus <- tibble::tibble(
chapter = 1:4,
text = c(
'the hero was brave courageous strong and victorious in battle',
'disaster struck terrible losses failure defeat mourning grief',
'love joy happiness beautiful peaceful wonderful morning',
'evil darkness corrupt wicked terrible pain suffering fear'
)
)
bing_sentiment <- corpus |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('bing'), by = 'word') |>
count(chapter, sentiment) |>
tidyr::pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) |>
mutate(net = positive - negative)
print(bing_sentiment)按章节或部分分析情感
要跟踪叙事弧线中的情感变化,可以计算每章或滚动窗口的净情感。这会揭示情绪结构:上升发展、高潮和结局。使用 ggplot2 搭配 geom_line() 或 geom_bar(),将这条弧线可视化。
library(tidytext)
library(dplyr)
library(ggplot2)
# Simulate a 10-chapter story arc
set.seed(42)
chapters <- tibble::tibble(
chapter = 1:10,
text = c(
'peaceful beautiful joy love happy wonderful',
'good friends happy carefree enjoyable fun',
'worried anxious trouble fear uncertain dark',
'danger terrible threat awful pain suffering',
'fear horror disaster terrible devastation loss',
'fight battle struggle hard difficult challenge',
'hope courage determination brave strong resist',
'triumph victory success celebrate joy love',
'relief peace gratitude wonderful blessed happy',
'love joy peace beautiful grateful wonderful'
)
)
arc <- chapters |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('afinn'), by = 'word') |>
group_by(chapter) |>
summarise(net_sentiment = sum(value))
ggplot(arc, aes(chapter, net_sentiment)) +
geom_line(color = 'steelblue', linewidth = 1.2) +
geom_hline(yintercept = 0, linetype = 'dashed') +
labs(x = 'Chapter', y = 'Net Sentiment', title = 'Story Sentiment Arc') +
theme_minimal()NRC 词典:情感类别
NRC 词典(Saif Mohammad 与 Peter Turney)将 13,901 个词分为八种情感(愤怒、期待、厌恶、恐惧、喜悦、悲伤、惊讶、信任),另外还分为正面和负面。使用 filter(sentiment == 'joy') 按情感筛选。
library(tidytext)
library(dplyr)
nrc <- get_sentiments('nrc')
cat('NRC size:', nrow(nrc), '\n')
cat('Emotions:', paste(unique(nrc$sentiment), collapse = ', '), '\n')
# Words associated with 'joy'
joy_words <- nrc |> filter(sentiment == 'joy')
cat('\nJoy words:', nrow(joy_words), '\n')
cat('Sample:', head(joy_words$word, 10), '\n')
# Count words per emotion
nrc |>
count(sentiment, sort = TRUE) |>
print()将 NRC 应用于语料库
将分词后的文本与 NRC 连接起来,分别为每种情感评分。使用 count(doc_id, sentiment),按文档和情感进行汇总,以查看每篇文档中占主导地位的情感。
library(tidytext)
library(dplyr)
docs <- tibble::tibble(
doc_id = c(1, 1, 2, 2, 3, 3),
text = c(
'wonderful joyful happy love peace',
'excited surprise anticipation trust',
'fear anger terrible hate disgust',
'dark horrible awful suffering pain',
'curious wonder discovery learning',
'hope trust anticipation future growth'
)
)
nrc_scores <- docs |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('nrc'), by = 'word') |>
filter(!sentiment %in% c('positive', 'negative')) |> # keep only emotions
count(doc_id, sentiment, sort = TRUE)
cat('Emotion counts per document:\n')
print(nrc_scores)词云概念
词云将词频可视化为大小与计数成比例的文字。wordcloud 或 wordcloud2 程序包可以根据词语/频率数据框生成词云。使用 Bing 词典按情感为词语着色,即可生成带有情感色彩的词云。
library(tidytext)
library(dplyr)
# Prepare word frequencies coloured by Bing sentiment
corpus_text <- tibble::tibble(
text = c(
'excellent performance amazing results love beautiful',
'terrible failure poor broken horrible waste',
'brilliant outstanding success happy wonderful joy',
'awful disappointing bad slow useless frustrating'
)
)
word_freq <- corpus_text |>
unnest_tokens(word, text) |>
count(word, sort = TRUE) |>
left_join(get_sentiments('bing'), by = 'word') |>
mutate(
sentiment = replace(sentiment, is.na(sentiment), 'neutral'),
colour = case_when(
sentiment == 'positive' ~ '#2196F3',
sentiment == 'negative' ~ '#F44336',
TRUE ~ '#9E9E9E'
)
)
print(word_freq)
# In practice: wordcloud2(word_freq[, c('word','n')], color = word_freq$colour)基于词典的情感分析的局限
基于词典的情感分析存在一些已知的失效情况:否定(“not good”会被评分为正面)、讽刺(“oh great, another bug”)、领域不匹配(“sick”在俚语中可能表示正面),以及词汇表外的词。在解释结果时,请考虑这些局限。
library(tidytext)
library(dplyr)
# Negation problem
neg_examples <- tibble::tibble(
text = c(
'not good at all', # negative, but 'good' scores +3
'not bad', # positive, but 'bad' scores -3
'sick beats bro' # slang positive, 'sick' is negative in AFINN
)
)
scored <- neg_examples |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('afinn'), by = 'word')
cat('Lexicon scores (naive - ignores negation):\n')
print(scored[, c('word', 'value')])
cat('\nNote: "not" is a stop word - the negation is lost!\n')快速检查
您使用 inner_join(tokens, afinn, by = 'word') 进行情感评分。词元中那些不在 AFINN 词典中的词会怎样?
回顾:情感分析
要点:
- 三种主要词典:AFINN(评分范围 −5 到 +5)、Bing(正面/负面)、NRC(8 种情感)
get_sentiments('afinn')/'bing'/'nrc'将词典提取为 tibbleinner_join(tokens, lexicon, by = 'word')只为匹配到的词评分(未匹配的词会被丢弃)- 净情感 =
group_by(doc) |> summarise(sentiment = sum(value)) - Bing:比较每篇文档或每个部分中的
positive - negative词数 - NRC:按情感名称筛选,以单独分析恐惧、喜悦、愤怒等情感
- 主要局限:基于词典的方法无法处理否定、讽刺或领域俚语
library(tidytext)
library(dplyr)
tibble::tibble(text = 'excellent amazing love joy beautiful happy') |>
unnest_tokens(word, text) |>
inner_join(get_sentiments('afinn'), by = 'word') |>
summarise(net_sentiment = sum(value)) |>
print()常见问题解答
「在 R 中进行情感分析」课时是免费的吗?
是的 — 「在 R 中进行情感分析」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。
「在 R 中进行情感分析」这节课中我会学到什么?
将词元与情感词典连接,以衡量正面或负面语气 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 R Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「在 R 中进行情感分析」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 R Academy 课中编写并运行代码吗?
能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 分词与停用词移除
- TF-IDF 与词频分析
- 在 R 中进行情感分析
- 使用 LDA 进行主题建模