inhaltsanalyse-mit-r.de

Wie auch einige andere hier behandelte Verfahren hat die Sentimentanalyse ihre Wurzeln in der Computerlinguistik und Informatik, wird aber seit einigen Jahren auch zunehmend in den Sozialwissenschaften angewandt, um ganz unterschiedliche Texte automatisch zu klassifizieren, etwa Parlamentsdebatten, Freitextantworten in Befragungen, oder Social Media-Diskurse. Ziel der Sentimentanalyse ist die Bestimmung der Polarität eines Textes, womit gemeint ist, ob die darin zum Ausdruck gebrachten Emotionen eher positiv oder negativ sind. Dies geschieht häufig durch Wortlisten und über das Auszählen von Begriffen, die zuvor den Kategorien positiv oder negativ zugeordnet wurden. In vielen Verfahren wird das Resultat anachließend skaliert, oder es werden andere Schritte angewandt, um fehlerhafte Klassifizierungen zu vermeiden. Diese treten vor allem dann auf, wenn Negation oder Ironie verwendet werden, aber auch, wenn der Gegenstand der positiven oder negativen Ausdrücke wechselt oder unklar ist. Unsprünglich wurde die Sentimentanalyse auf Produktbewertungen auf E-Commerence-Plattformen wie Amazon.com getestet, wo diese Probleme eine relativ geringe Rolle spielen. Bei Pressetexten oder Diskursen in den sozialen Medien hingegen, ist oft schwerer zu bewerten, auf was sich eine Sentimentbewertung bezieht, oder welches Sentimenniveau etwa als ‘normal’ betrachtet werden sollte. So kommen beispielsweise in Pressetexten generell wenig Emotionen zum Ausdruck, und die negativen Begriffe überwiegen häufig, ohne dass dies notwendigerweise auf einen schlechten Zustand der Welt zurückzuführen wäre. Schließlich sollte man sich vor Augen führen, dass die Sentimentanalyse ein heuristisches Verfahren ist, dass immer auch fehlerhafte Einzelklassifikationen produziert, was aber idealerweise nicht zu stark ins Gewicht fällt, wenn man etwas Veränderungen im Sentimentverlauf über die Zeit untersucht.

Was die technische Umsetzung angeht, so gehören dieser Abschnitt und das nächste Kapitel 3b: Lexika insofern zusammen, als dass es sich bei beiden Ansätzen um ganz ähnliche Verfahren handelt. In beiden Fällen wird ein Lexikon (‘sentiment/topic dictionary’) verwendet, um eine Reihe von Einzelbegriffen in einer Kategorie zusammenzufassen.

Wir verwenden in diesem Kapitel fünf unterschiedliche Sentimentlexika, davon drei in englischer Sprache und zwei für Deutsch:

Diese Lexika sind lediglich Listen von Wörtern, welche wie oben beschrieben den Kategorien postiv oder negativ zugeordnet sind. Zum Teil existiert auch noch eine dritte Kategorie neutral, desweiteren können Begriffe auch mehreren Kategorien zugeordnet sein, oder neben einer Zuordnung der Polarität auch noch eine Sentimentstärke zugeschrieben bekommen. Die hier vorgestellte Technik ist vergleichsweise primitiv, weil sie lediglich Wörter auszählt, allerdings lassen sich die Verfahren leicht noch verfeinern (vgl. bspw. diesen Beitrag von Christian Rauh zur Validierung politischer Sentiment-Lexika). Auch Verfahren die gewichten oder andere Kniffe für die Verringerung der Fehlerrate einsetzen, funktionieren so — die Sentimentanalye ist effektiv, aber auch alles andere als Hexenwerk.

Diese Lexika wenden wir folgend auf vier Datensätze an: das bereits bekannte Sherlock Holmes—Korpus, einen Datensatz aus Tweets von Donald Trump un Hillary Clinten, ein Korpus Schweizer Tageszeitugen mit Artikeln zur Finanzkrise, die zwischen 2007 und 2012 verfasst wurden, und schließlich noch einen Debattenkorpus des 18. Deutschen Bundestags (2013 bis 2017). Auf die Zusammenstellung der Korpora gehen wir später noch ein.

Installation und Laden der benötigten R-Bibliotheken, Laden des Korpus

Zunächst werden wieder die notwendigen Bibliotheken geladen. Neu ist die Bibliothek scales die bei der Normalisierung von Sentiment—Scores zum Einsatz kommt. Dann wird in einem zweiten Schritt das Sherlock-Korpus eingelesen und aufbereitet und dann Korpus-Statistiken berechnet. Schließlich erstellen wir wieder eine DFM (vgl. Kapitel 1), da wir diese später noch benötigen.

# Installation und Laden der Bibliotheken
if(!require("quanteda")) install.packages("quanteda")
## Loading required package: quanteda
## Package version: 1.3.4
## Parallel computing: 2 of 4 threads used.
## See https://quanteda.io for tutorials and examples.
## 
## Attaching package: 'quanteda'
## The following object is masked from 'package:utils':
## 
##     View
if(!require("readtext")) install.packages("readtext")
## Loading required package: readtext
if(!require("tidyverse")) install.packages("tidyverse")
## Loading required package: tidyverse
## ── Attaching packages ──────────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.0.0     ✔ purrr   0.2.5
## ✔ tibble  1.4.2     ✔ dplyr   0.7.6
## ✔ tidyr   0.8.1     ✔ stringr 1.3.1
## ✔ readr   1.1.1     ✔ forcats 0.3.0
## ── Conflicts ─────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
if(!require("scales")) install.packages("scales")
## Loading required package: scales
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
theme_set(theme_bw())

# Laden der Sherlock Holmes-Daten (bereits als RData-File gespeichert)
load("daten/sherlock/sherlock.korpus.RData")

Erstellung eines Lexikons in quanteda

Wir beginnen zunächst mit einer Sentimentanalyse der Sherlock Holmes-Erzählungen, um bei einem bereits aus Kapitel 1 und 2 vertrauten Korpus zu bleiben. In einem ersten Schritt erstellen wir ein sehr einfaches Ad hoc-Lexikon aus nur sechs Begriffen, um die Struktur eines Lexikons in quanteda zu illustrieren. Dies geschieht mit dem quanteda-Befehl dictionary. Dictionary() akzeptiert eine Reihe von Standardformaten (dazu später noch mehr), aber auch Vektoren, welche die Begriffe enthalten, die eine abstrakte Kategorie operationalisieren. Beliebig viele Kategorien können so definiert und dann mit tausenden von Begriffen ‘befüllt’ werden. Auch Kategorien mit mehreren hierarchischen Ebenen sind möglich — dazu im nächsten Kapitel noch etwas mehr.

test.lexikon <- dictionary(list(posititive.begriffe = c("glück", "freude", "licht"), negative.begriffe = c("trauer", "wut", "dunkelheit")))
test.lexikon
## Dictionary object with 2 key entries.
## - [posititive.begriffe]:
##   - glück, freude, licht
## - [negative.begriffe]:
##   - trauer, wut, dunkelheit

Erste Sentiment-Analyse mit dem Sherlock Holmes-Korpus

Mit diesem Lexikon können wir mit unserem englischsprachigen Korpus wenig konkretes anfangen, daher wechseln wir besser zu einem echten Sentimentlexikon. In einem zweiten Schritt lesen wir mit dem Befehl scan das Bing Liu Sentiment Lexikon in R ein. Dieses Lexikon umfasst über 6.700 englischsprachige Begriffe die in zwei einfachenn Textdateien abgelegt sind, die jeweils ein Wort je Zeile enthalten. Wir überspringen mit dem Argument skip die ersten 35 Zeilen, da diese Metainformationen über das Lexikon enthalten. Das Argument quiet verhindet die Ausgabe einer Statusmeldung.

positive.woerter.bl <- scan("lexika/bingliu-positive-words.txt", what = "char", sep = "\n", skip = 35, quiet = T)
negative.woerter.bl <- scan("lexika/bingliu-negative-words.txt", what = "char", sep = "\n", skip = 35, quiet = T)

Nun erstellen wir das Lexikon mithilfe der gerade eingelesenen Textvektoren. Dies erfolgt wieder mit der Funktion dictionary(), diesmal mit den gerade eingelesenen Vektoren als Argument.

sentiment.lexikon <- dictionary(list(positive = positive.woerter.bl, negative = negative.woerter.bl))
str(sentiment.lexikon)
## Formal class 'dictionary2' [package "quanteda"] with 2 slots
##   ..@ .Data       :List of 2
##   .. ..$ :List of 1
##   .. .. ..$ : chr [1:2006] "a+" "abound" "abounds" "abundance" ...
##   .. ..$ :List of 1
##   .. .. ..$ : chr [1:4783] "2-faced" "2-faces" "abnormal" "abolish" ...
##   ..@ concatenator: chr " "

Wie man sieht, sind nun mehrere tausend Begriffe den beiden Kategorien des Lexikons zugeordnet worden. Jetzt können wir eine DFM berechnen, welche das erstellte Lexikon auf das Korpus anwendet.

meine.dfm.sentiment <- dfm(korpus, dictionary = sentiment.lexikon)
meine.dfm.sentiment
## Document-feature matrix of: 12 documents, 2 features (0% sparse).
## 12 x 2 sparse Matrix of class "dfm"
##                                        features
## docs                                    positive negative
##   A Scandal in Bohemia                       248      204
##   The Red-headed League                      272      217
##   A Case of Identity                         200      194
##   The Boscombe Valley Mystery                195      295
##   The Five Orange Pips                       149      213
##   The Man with the Twisted Lip               193      298
##   The Adventure of the Blue Carbuncle        200      226
##   The Adventure of the Speckled Band         205      375
##   The Adventure of the Engineer's Thumb      223      246
##   The Adventure of the Noble Bachelor        237      208
##   The Adventure of the Beryl Coronet         276      280
##   The Adventure of the Copper Beeches        287      311

Was ist geschehen? Alle Nennungen der rund 6.700 im Bing Liu Lexikon enthaltenen Begriffe in den zwölf Sherlock Holmes—Romanen sind jeweils durch die ihnen zugeordnete Kategorie ersetzt worden. Sämtliche Begriffe, die nicht im Lexikon vorkommen, fallen weg. Dadurch bleibt eine Tabelle zurück, die nur noch zwei Spalten enthält — die Summe aller positiven und negativen Begriffe.

Das folgende Plot zeigt diese Verteilung in den zwölf Sherlock Holmes-Erzählungen.

sentiment <- convert(meine.dfm.sentiment, "data.frame") %>%
  gather(positive, negative, key = "Polarität", value = "Wörter") %>% 
  mutate(document = as_factor(document)) %>% 
  rename(Roman = document)
ggplot(sentiment, aes(Roman, Wörter, colour = Polarität, group = Polarität)) + geom_line(size = 1) + scale_colour_brewer(palette = "Set1") + theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + ggtitle("Sentiment-Scores in zwölf Sherlock Holmes-Romanen")