R Academy · Lekcja

Analiza sentymentu w R

Łącz tokeny ze słownikami sentymentu, aby mierzyć pozytywny lub negatywny wydźwięk.

Lekcja 3 z 413 kroki

Analiza sentymentu w R to bezpłatna lekcja R Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.

Przegląd analizy sentymentu

Analiza sentymentu przypisuje tekstowi nacechowanie emocjonalne. Podejście tidytext polega na dopasowaniu poszczególnych słów do leksykonu sentymentu i agregowaniu wyników. Dostępne są trzy wbudowane leksykony: AFINN (wartości liczbowe), Bing (pozytywne/negatywne) i NRC (kategorie emocji).

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')

Leksykon AFINN przypisuje 2477 angielskim słowom wartości całkowite od −5 (bardzo negatywne) do +5 (bardzo pozytywne). Został opracowany przez Finna Årupa Nielsena i dobrze sprawdza się w przypadku mediów społecznościowych oraz tekstów recenzji.

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')

Leksykon Bing (Bing Liu i współautorzy) klasyfikuje 6786 słów jako pozytywne lub negatywne. Jest większy niż AFINN i dobrze nadaje się do recenzji produktów oraz opinii klientów, w których wystarcza prosta klasyfikacja biegunowości.

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: Ocenianie słów

inner_join(tokens, afinn, by = 'word') zachowuje tylko tokeny występujące w leksykonie AFINN, dołączając do nich oceny. Słowa, których nie ma w leksykonie, są po cichu pomijane — jest to zarówno zaleta (koncentracja na znanych słowach wyrażających sentyment), jak i ograniczenie.

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')])

Sentyment netto dla dokumentu

Zsumuj oceny AFINN dla każdego dokumentu za pomocą group_by(document) |> summarise(sentiment = sum(value)), aby uzyskać wynik sentymentu netto. Sumy dodatnie wskazują na ogólnie pozytywny sentyment, a sumy ujemne — na negatywny.

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)

Sentyment Bing: liczba słów pozytywnych i negatywnych

Korzystając z leksykonu Bing, porównaj liczbę pozytywnych i negatywnych słów w każdym dokumencie. Oblicz sentiment = positive_n - negative_n, aby uzyskać wynik biegunowości netto, albo przedstaw obie liczby na pogrupowanym wykresie słupkowym, aby zobaczyć ich strukturę.

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)

Sentyment według rozdziału lub sekcji

Aby śledzić sentyment w całym przebiegu narracji, oblicz sentyment netto dla każdego rozdziału lub okna kroczącego. Ujawni to strukturę emocjonalną: narastanie akcji, punkt kulminacyjny i rozwiązanie. Użyj ggplot2 wraz z geom_line() lub geom_bar(), aby zwizualizować przebieg.

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()

Leksykon NRC: kategorie emocji

Leksykon NRC (Saif Mohammad i Peter Turney) kategoryzuje 13 901 słów według ośmiu emocji (złość, oczekiwanie, wstręt, strach, radość, smutek, zaskoczenie, zaufanie), a także według sentymentu pozytywnego i negatywnego. Filtruj według emocji za pomocą 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()

Zastosowanie NRC do korpusu

Połącz tokenizowany tekst z NRC, aby ocenić każdą emocję osobno. Agreguj dane według dokumentu i emocji za pomocą count(doc_id, sentiment), aby zobaczyć, które emocje dominują w poszczególnych dokumentach.

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)

Koncepcja chmury słów

Chmura słów wizualizuje częstotliwość występowania słów, przedstawiając je czcionką o rozmiarze proporcjonalnym do liczby wystąpień. Pakiety wordcloud lub wordcloud2 generują takie chmury na podstawie ramki danych zawierającej słowa i ich częstotliwości. Pokoloruj słowa według sentymentu, korzystając z leksykonu Bing, aby uzyskać chmurę z kolorami oznaczającymi sentyment.

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)

Ograniczenia analizy sentymentu opartej na leksykonie

Analiza sentymentu oparta na leksykonie ma znane przypadki niepowodzeń: negację („not good” zostaje ocenione jako pozytywne), sarkazm („oh great, another bug”), niedopasowanie do dziedziny („sick” ma pozytywne znaczenie w slangu) oraz słowa spoza słownika. Uwzględnij te ograniczenia podczas interpretowania wyników.

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')

Szybkie sprawdzenie

Używasz inner_join(tokens, afinn, by = 'word') do oceniania sentymentu. Co dzieje się ze słowami w tokenach, których NIE ma w leksykonie AFINN?

Podsumowanie: analiza sentymentu

Najważniejsze informacje:

  • Trzy główne leksykony: AFINN (oceny od −5 do +5), Bing (pozytywne/negatywne), NRC (8 emocji)
  • get_sentiments('afinn') / 'bing' / 'nrc' pobiera leksykon jako tibble
  • inner_join(tokens, lexicon, by = 'word') ocenia tylko dopasowane słowa (niedopasowane są pomijane)
  • Sentyment netto = group_by(doc) |> summarise(sentiment = sum(value))
  • Bing: porównuj liczbę słów positive - negative w każdym dokumencie lub sekcji
  • NRC: filtruj według nazwy emocji, aby wyodrębnić między innymi strach, radość i złość
  • Główne ograniczenie: metody oparte na leksykonie nie radzą sobie z negacją, sarkazmem ani slangiem charakterystycznym dla danej dziedziny
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()
Bezpłatny start

Ucz się R dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
43
Lekcje
159

Często zadawane pytania

Czy lekcja „Analiza sentymentu w R” jest bezpłatna?

Tak — pełny tekst „Analiza sentymentu w R” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Analiza sentymentu w R”?

Łącz tokeny ze słownikami sentymentu, aby mierzyć pozytywny lub negatywny wydźwięk. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć R Academy?

Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Analiza sentymentu w R”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?

Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tokenizacja i usuwanie słów pustych
  2. TF-IDF i analiza częstości terminów
  3. Analiza sentymentu w R
  4. Modelowanie tematów za pomocą LDA
← Powrót do R Academy