Analisi del sentiment in R
Unisca i token ai lessici del sentiment per misurare il tono positivo o negativo
Analisi del sentiment in R è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
Panoramica sull'analisi del sentiment
L'analisi del sentiment assegna una valenza emotiva al testo. L'approccio di tidytext confronta le singole parole con un lessico del sentiment e aggrega i punteggi. Sono disponibili tre lessici integrati: AFINN (punteggi numerici), Bing (positivo/negativo) e NRC (categorie emotive).
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')
Il lessico AFINN assegna punteggi interi da −5 (molto negativo) a +5 (molto positivo) a 2.477 parole inglesi. È stato compilato da Finn Årup Nielsen e funziona bene con i testi dei social media e delle recensioni.
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')
Il lessico Bing (Bing Liu e altri) classifica 6.786 parole come positive o negative. È più ampio di AFINN e adatto alle recensioni di prodotti e ai feedback dei clienti quando è sufficiente una semplice polarità.
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: Assegnare punteggi alle parole
inner_join(tokens, afinn, by = 'word') mantiene solo i token presenti nel lessico AFINN, aggiungendo i relativi punteggi. Le parole che non sono presenti nel lessico vengono eliminate senza segnalazione: questo è al tempo stesso un vantaggio (si concentra sulle parole note associate al sentiment) e un limite.
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')])Sentiment netto per documento
Sommi i punteggi AFINN per documento con group_by(document) |> summarise(sentiment = sum(value)) per ottenere un punteggio di sentiment netto. Somme positive indicano un sentiment complessivamente positivo; somme negative indicano un sentiment negativo.
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)Sentiment Bing: conteggi positivi e negativi
Con il lessico Bing, confronti il numero di parole positive e negative per documento. Calcoli sentiment = positive_n - negative_n per ottenere un punteggio di polarità netto, oppure rappresenti entrambi i conteggi con barre raggruppate per visualizzarne la composizione.
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)Sentiment per capitolo o sezione
Per seguire l'andamento del sentiment lungo l'arco narrativo, calcoli il sentiment netto per capitolo o su una finestra mobile. In questo modo emerge la struttura emotiva: sviluppo dell'azione, climax, risoluzione. Usi ggplot2 con geom_line() o geom_bar() per visualizzare l'arco narrativo.
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()Lessico NRC: categorie delle emozioni
Il lessico NRC (Saif Mohammad e Peter Turney) classifica 13.901 parole in otto emozioni (rabbia, anticipazione, disgusto, paura, gioia, tristezza, sorpresa, fiducia), oltre alle categorie positiva/negativa. Filtri per emozione con 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()Applicazione di NRC a un corpus
Unisci il testo tokenizzato con NRC per assegnare separatamente un punteggio a ogni emozione. Aggrega per documento ed emozione usando count(doc_id, sentiment) per vedere quali emozioni predominano in ciascun documento.
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)Concetto di wordcloud
Una nuvola di parole visualizza la frequenza delle parole usando dimensioni del testo proporzionali al conteggio. I pacchetti wordcloud o wordcloud2 le generano a partire da un data frame di parole e frequenze. Colora le parole in base al sentiment usando il lessico Bing, così da ottenere una nuvola colorata secondo il sentiment.
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)Limiti dell'analisi del sentiment basata su lessici
L'analisi del sentiment basata su lessici presenta alcuni casi problematici noti: negazione ("not good" viene valutato come positivo), sarcasmo ("oh great, another bug"), differenze tra domini ("sick" è positivo nello slang) e parole fuori dal vocabolario. Tenga presenti questi limiti nell'interpretare i risultati.
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')Verifica rapida
Usa inner_join(tokens, afinn, by = 'word') per assegnare i punteggi del sentiment. Che cosa succede alle parole presenti nei token ma NON nel lessico AFINN?
Riepilogo: analisi del sentiment
Punti chiave:
- Tre lessici principali: AFINN (punteggi da −5 a +5), Bing (positivo/negativo), NRC (8 emozioni)
get_sentiments('afinn')/'bing'/'nrc'recupera il lessico sotto forma di tibbleinner_join(tokens, lexicon, by = 'word')assegna i punteggi solo alle parole corrispondenti (quelle senza corrispondenza vengono eliminate)- Sentiment netto =
group_by(doc) |> summarise(sentiment = sum(value)) - Bing: confronta i conteggi delle parole
positive - negativeper documento o sezione - NRC: filtra per nome dell'emozione per isolare paura, gioia, rabbia ecc.
- Limite principale: i metodi basati su lessici non gestiscono negazioni, sarcasmo o slang specifico del dominio
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()Domande Frequenti
La lezione «Analisi del sentiment in R» è gratuita?
Sì — il testo completo di «Analisi del sentiment in R» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «Analisi del sentiment in R»?
Unisca i token ai lessici del sentiment per misurare il tono positivo o negativo Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Analisi del sentiment in R»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Tokenizzazione e rimozione delle stop word
- TF-IDF e analisi della frequenza dei termini
- Analisi del sentiment in R
- Topic modeling con LDA