Sentiment-Wörterbuch erstellen

Bei der Textanalyse (Textmining) ist die Sentiment-Analyse eine typische Tätigkeit. Natürlich steht und fällt die Qualität der Sentiment-Analyse mit der Qualität des verwendeten Wörterbuchs (was nicht heißt, dass man nicht auch auf andere Klippen schellen kann).

Der Zweck dieses Posts ist es, eine Sentiment-Lexikon in deutscher Sprache einzulesen.

Dazu wird das Sentiment-Lexikon dieser Quelle verwendet (CC-BY-NC-SA 3.0). In diesem Paper finden sich Hintergründe. Von dort lassen sich die Daten herunter laden. Im folgenden gehe ich davon aus, dass die Daten herunter geladen sind und sich im Working Directory befinden.

Wir benötigen diese Pakete (es ginge auch über base):

library(stringr)
library(readr)
library(dplyr)

Dann lesen wir die Daten ein, zuerst die Datei mit den negativen Konnotationen:

neg_df <- read_tsv("SentiWS_v1.8c_Negative.txt", col_names = FALSE)
names(neg_df) <- c("Wort_POS", "Wert", "Inflektionen")

glimpse(neg_df)
#> Observations: 1,818
#> Variables: 3
#> $ Wort_POS     <chr> "Abbau|NN", "Abbruch|NN", "Abdankung|NN", "Abdämp...
#> $ Wert         <dbl> -0.0580, -0.0048, -0.0048, -0.0048, -0.0048, -0.3...
#> $ Inflektionen <chr> "Abbaus,Abbaues,Abbauen,Abbaue", "Abbruches,Abbrü...

Dann parsen wir aus der ersten Spalte (Wort_POS) zum einen den entsprechenden Begriff (z.B. “Abbau”) und zum anderen die Wortarten-Tags (eine Erläuterung zu den Wortarten-Tags findet sich hier).

neg_df %>% 
  mutate(Wort = str_sub(Wort_POS, 1, regexpr("\\|", .$Wort_POS)-1),
         POS = str_sub(Wort_POS, start = regexpr("\\|", .$Wort_POS)+1)) -> neg_df

str_sub parst zuerst das Wort. Dazu nehmen wir den Wort-Vektor Wort_POS, und für jedes Element wird der Text von Position 1 bis vor dem Zeichen | geparst; da der Querstrich ein Steuerzeichen in Regex muss er escaped werden. Für POS passiert das gleiche von Position |+1 bis zum Ende des Text-Elements.

Das gleiche wiederholen wir für positiv konnotierte Wörter.

pos_df <- read_tsv("SentiWS_v1.8c_Positive.txt", col_names = FALSE)
names(pos_df) <- c("Wort_POS", "Wert", "Inflektionen")
pos_df %>% 
  mutate(Wort = str_sub(Wort_POS, 1, regexpr("\\|", .$Wort_POS)-1),
         POS = str_sub(Wort_POS, start = regexpr("\\|", .$Wort_POS)+1)) -> pos_df

Schließlich schweißen wir beide Dataframes in einen:

bind_rows("neg" = neg_df, "pos" = pos_df, .id = "neg_pos") -> sentiment_df
sentiment_df %>% select(neg_pos, Wort, Wert, Inflektionen, -Wort_POS) -> sentiment_df
knitr::kable(head(sentiment_df))
neg_pos Wort Wert Inflektionen
neg Abbau -0.058 Abbaus,Abbaues,Abbauen,Abbaue
neg Abbruch -0.005 Abbruches,Abbrüche,Abbruchs,Abbrüchen
neg Abdankung -0.005 Abdankungen
neg Abdämpfung -0.005 Abdämpfungen
neg Abfall -0.005 Abfalles,Abfälle,Abfalls,Abfällen
neg Abfuhr -0.337 Abfuhren

Literatur

R. Remus, U. Quasthoff & G. Heyer: SentiWS - a Publicly Available German-language Resource for Sentiment Analysis. In: Proceedings of the 7th International Language Ressources and Evaluation (LREC'10), 2010