0Pricing
R Academy · Lektion

Sentimentanalyse in R

Verbinden Sie Tokens mit Sentiment-Lexika, um positive und negative Tonalität zu messen

Sentimentanalyse in R ist eine kostenlose R Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des R Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.

Überblick über die Sentimentanalyse

Die Sentimentanalyse ordnet Texten eine emotionale Wertigkeit zu. Der tidytext-Ansatz gleicht einzelne Wörter mit einem Sentimentlexikon ab und aggregiert die Bewertungen. Drei integrierte Lexika stehen zur Verfügung: AFINN (numerische Werte), Bing (positiv/negativ) und NRC (Emotionskategorien).

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

Das AFINN-Lexikon weist 2.477 englischen Wörtern ganzzahlige Werte von −5 (sehr negativ) bis +5 (sehr positiv) zu. Es wurde von Finn Årup Nielsen zusammengestellt und eignet sich gut für Texte aus sozialen Medien und Rezensionen.

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

Das Bing-Lexikon (Bing Liu et al.) klassifiziert 6.786 Wörter entweder als positiv oder negativ. Es ist größer als AFINN und eignet sich gut für Produktrezensionen und Kundenfeedback, bei denen eine einfache Polarität ausreicht.

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: Wörter bewerten

inner_join(tokens, afinn, by = 'word') behält nur Tokens, die im AFINN-Lexikon vorkommen, und fügt deren Bewertungen hinzu. Wörter, die nicht im Lexikon enthalten sind, werden stillschweigend entfernt – das ist zugleich eine Stärke (der Fokus liegt auf bekannten Sentimentwörtern) und eine Einschränkung.

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

Netto-Sentiment pro Dokument

Summieren Sie die AFINN-Bewertungen pro Dokument mit group_by(document) |> summarise(sentiment = sum(value)), um einen Netto-Sentimentwert zu erhalten. Positive Summen weisen auf ein insgesamt positives Sentiment hin, negative Summen auf ein negatives Sentiment.

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-Sentiment: Positive und negative Häufigkeiten

Vergleichen Sie mit dem Bing-Lexikon die Häufigkeiten positiver und negativer Wörter pro Dokument. Berechnen Sie sentiment = positive_n - negative_n für einen Netto-Polaritätswert oder stellen Sie beide Häufigkeiten als gruppierte Balken dar, um die Zusammensetzung zu sehen.

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 nach Kapitel oder Abschnitt

Um das Sentiment entlang eines narrativen Verlaufs zu verfolgen, berechnen Sie das Netto-Sentiment pro Kapitel oder über ein gleitendes Fenster. Dadurch wird die emotionale Struktur sichtbar: ansteigende Handlung, Höhepunkt, Auflösung. Verwenden Sie ggplot2 mit geom_line() oder geom_bar() zur Visualisierung des Verlaufs.

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-Lexikon: Emotionskategorien

Das NRC-Lexikon (Saif Mohammad & Peter Turney) kategorisiert 13.901 Wörter in acht Emotionen (anger, anticipation, disgust, fear, joy, sadness, surprise, trust) sowie positive/negative. Filtern Sie nach Emotion mit 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 auf einen Korpus anwenden

Verknüpfen Sie tokenisierten Text mit NRC, um jede Emotion separat zu bewerten. Aggregieren Sie nach Dokument und Emotion mit count(doc_id, sentiment), um zu sehen, welche Emotionen in den einzelnen Dokumenten vorherrschen.

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)

Konzept der Wordcloud

Eine wordcloud visualisiert Worthäufigkeiten, indem die Textgröße proportional zur Häufigkeit dargestellt wird. Die Pakete wordcloud oder wordcloud2 erzeugen Wordclouds aus einem Dataframe mit Wörtern und Häufigkeiten. Färben Sie die Wörter mithilfe des Bing-Lexikons nach ihrem Sentiment ein, um eine nach Sentiment eingefärbte Wordcloud zu erhalten.

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)

Einschränkungen lexikonbasierter Sentimentanalyse

Die lexikonbasierte Sentimentanalyse weist bekannte Fehlerquellen auf: Negation ("not good" wird als positiv bewertet), Sarkasmus ("oh great, another bug"), fehlende Übereinstimmung mit der Domäne ("sick" ist im Slang positiv) und Wörter außerhalb des Vokabulars. Berücksichtigen Sie diese Einschränkungen bei der Interpretation der Ergebnisse.

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

Kurzer Check

Sie verwenden inner_join(tokens, afinn, by = 'word') zur Sentimentbewertung. Was geschieht mit Wörtern in Ihren Tokens, die NICHT im AFINN-Lexikon enthalten sind?

Zusammenfassung: Sentimentanalyse

Wichtigste Erkenntnisse:

  • Drei wichtige Lexika: AFINN (Bewertungen von −5 bis +5), Bing (positiv/negativ), NRC (8 Emotionen)
  • get_sentiments('afinn') / 'bing' / 'nrc' ruft das Lexikon als Tibble ab
  • inner_join(tokens, lexicon, by = 'word') bewertet nur übereinstimmende Wörter (nicht übereinstimmende werden entfernt)
  • Netto-Sentiment = group_by(doc) |> summarise(sentiment = sum(value))
  • Bing: Vergleichen Sie die Häufigkeiten positiver und negativer Wörter pro Dokument oder Abschnitt
  • NRC: Filtern Sie nach dem Namen der Emotion, um beispielsweise Angst, Freude oder Wut isoliert zu betrachten
  • Wichtige Einschränkung: Lexikonbasierte Verfahren berücksichtigen keine Negation, keinen Sarkasmus und keinen domänenspezifischen Slang
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()

Häufig gestellte Fragen

Ist die Lektion „Sentimentanalyse in R“ kostenlos?

Ja — der vollständige Text von „Sentimentanalyse in R“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des R Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Sentimentanalyse in R“?

Verbinden Sie Tokens mit Sentiment-Lexika, um positive und negative Tonalität zu messen Du übst R Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um R Academy zu starten?

Keine Vorkenntnisse erforderlich. R Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Sentimentanalyse in R“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser R Academy-Lektion Code schreiben und ausführen?

Ja. Jede R Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Tokenisierung und Entfernen von Stoppwörtern
  2. TF-IDF- und Termfrequenzanalyse
  3. Sentimentanalyse in R
  4. Topic Modeling mit LDA
← Zurück zu R Academy