12 Tutorial 12: Deskriptive Statistik & Diktionaere

In Tutorial 12 lernen Sie erste Analyseverfahren für Text kennen, spezifisch:

  • Wie Sie deskriptive Statistiken zu Ihrem Korpus enthalten
  • wie Sie die (gruppierte) Häufigkeit von Features analysieren
  • Was Keywords-in-Context sind und wie Sie diese analysieren
  • Was Ko-Okkurrenzen sind und wie Sie diese analysieren
  • Was Dikitionäre sind und wie Sie mit Hilfe dieser Text analysieren

Wir arbeiten wieder mit einem Text-Korpus, der im R-Package Quanteda bzw. Quanteda-Corpora Quanteda-Corpora-Package zurzeit im Entwicklungsmodus bereits enthalten ist.

Sie finden den Korpus in OLAT (via: Materialien / Datensätze für R) mit dem Namen immigration_news.rda. Bei diesen Dateien handelt es sich um Nachrichtenartikel aus Grossbritannien zum Thema Immigration aus dem Jahr 2014, die (leicht bearbeitet) bereits als R-Environment abgespeichert wurde. Die Daten befinden sich in einem ähnlichen Format, wie Sie sie erhalten würden, wenn Sie ihre Text mit dem readtext-Package einlesen würden.

Quelle der Daten: Nulty, P. & Poletti, M. (2014). “The Immigration Issue in the UK in the 2014 EU Elections: Text Mining the Public Debate.” Presentation at LSE Text Mining Conference 2014. Geladen via dem Quanteda-Corpus_Package.

Bitte laden Sie den Datensatz in Ihr R-Environment.

Wir bereiten den Korpus zunächst für eine Analyse grob vor (wie bereits in den letzten Tutorials gezeigt):

  • Wir speichern den Publikationsmonat der Dokumente ab, um diesen später für Vergleiche über Zeit anwenden zu können.
  • Wir entfernen das pattern für einen Zeilenumbruch \n
  • Wir führen die üblichen Preprocessing-Schritte durch, die im vorherigen Tutorial bereits erklärt wurden. Hier nutzen wir allerdings nur einige der vorab genannten Schritte.
## Removing features occurring:
##   - in fewer than 14.165 documents: 33,992
##   - in more than 2804.67 documents: 2
##   Total features removed: 33,994 (86.8%).
## Document-feature matrix of: 2,833 documents, 5,162 features (97.1% sparse).
##        features
## docs    support ukip continues grow labour heartlands miliband scared leo mckinstry
##   text1       2    7         1    1      8          2        4      1   1         1
##   text2       0    1         0    0      0          0        0      0   0         0
##   text3       0    1         0    0      0          0        0      0   0         0
##   text4       0    0         0    0      0          0        0      0   0         0
##   text5       0    1         0    0      0          0        0      0   0         0
##   text6       0    0         0    0      0          0        0      0   0         0
## [ reached max_ndoc ... 2,827 more documents, reached max_nfeat ... 5,152 more features ]

12.1 Deskriptive Statistiken zu Ihrem Korpus

12.1.1 Anzahl Dokumente

Zunächst wollen Sie wissen, wie viele Dokumente der Korpus enthält. Dafür nutzen den ndoc()-Befehl. Wir sehen: Es sind rund 2,800 Artikel.

## [1] 2833

12.1.2 Anzahl Features

Dann wollen wir wissen, wie viele Features der Korpus enthält. Wir sehen: Es sind etwas mehr als 5,000 Features nach der Bereinigung übrig geblieben.

## [1] 5162

12.1.3 Feature-Vorkommen

Lassen wir uns für jedes Feature jetzt ausgeben, wie häufig dieses vorkommt. Wir nutzen dafür den featfreq()-Befehl und speichern das Ergebnis in einem neuen dataframe-Objekt ab.

Die Namen der jeweiligen Features sind jetzt noch in den Zeilennamen abgespeichert, aber nicht als eigene Spalte. Wir nutzen den rownames-Befehl, um die Namen der jeweiligen Features als Variablen abzuspeichern:

##            freq    feature
## support     716    support
## ukip       3606       ukip
## continues    60  continues
## grow         72       grow
## labour     2144     labour
## heartlands   29 heartlands
## miliband    580   miliband
## scared       57     scared
## leo          29        leo
## mckinstry    20  mckinstry

So können wir uns z.B. ausgeben lassen, wie häufig ein bestimmtes Feature vorkommt, etwa das Wort crisis. Da wir kein Stemming benutzt haben, sollten wir daran denken, dass Features hier nicht mit ihren Wortstämmen vorliegen. Sonst müssten wir z.B. nach dem pattern cris suchen.

Jetzt suchen wir also z.B. nach dem pattern crisis:

## [1] 228

Das Wort Krise kommt also insgesamt 228 Mal vor.

12.1.4 Häufigste & seltenste Features

Jetzt wollen wir wissen: Welches sind die Features, die am häufigsten vorkommen?

##        said          mr        ukip immigration      people       party         one          uk     britain      farage 
##        5513        3779        3606        3533        3386        2821        2644        2511        2395        2329 
##      rights          eu         may      labour           ©    reserved        news     british        last   telegraph 
##        2326        2324        2183        2144        2090        1979        1970        1900        1899        1830

Und welche Features kommen am seltensten vor?

##       giles     reminds  successive bureaucrats    enduring       alarm        dire     stating   contender     pursuit 
##          15          15          15          15          15          15          15          15          15          15 
##      hinted     swiftly   indicator   backfired   onslaught       shore    veterans   extensive     avoided   uncertain 
##          15          15          15          15          15          15          15          15          15          15

12.1.5 Können wir das auch visualisieren?

Ein beliebter (aber unter vielen Wissenschaftler:innen inzwischen eher verpönter) Trend ist es, häufige Wörter zu visualisieren. Wie sehr das hilft, die eigenen Texte zu verstehen, sei mal dahingestellt. Zumindest sieht es schön aus.

Genutzt wird dafür die beliebte Wordcloud, die Wörter visualisiert - je grösser diese dargestellt werden, desto häufiger kommen sie vor. Wir lassen uns hier die häufigsten 50 Wörter visualisieren:

Anhand der Wordcloud können wir zumindest einige Dinge über unsere Texte erfahren - nämlich, dass diese englischsprachig sind und sich um britische Politik und/oder Immigration drehen.

12.2 Gruppierte Frequenz von Features

Eine simple deskriptive Analyse könnte z.B. sein, dass wir wissen wollen, wie sich das Vorkommen von Features über die Monate hinweg unterscheidet.

Um das herauszufinden, könnten wir uns die Frequenz dieses Features über verschiedene Gruppen hinweg - hier z.B. den Monat der Publikation des Artikels - ausgeben lassen:

Dazu setzen wir zunächst den Monat als Gruppierungsvariable, d.h. als Variable, anhand derer wir uns die Frequenz eines patterns ausgeben lassen wollen.

Wir weisen den jeweiligen Monat, in dem ein Artikel publiziert wurde, dabei sowohl als Character-Vektor als auch als numerischen Wert der DFM zu, damit wir die Entwicklung über Monate später von Monat 1 des Jahres (Januar) bis Monat 5 des Jahres (Mai) aufzeigen können, indem wir die Daten nach Monat chronologisch sortieren.

Dann lassen wir uns ein nach Monat gruppiertes document_feature_matrix-Objekt ausgeben.

Sie sehen hier, dass das Vorkommen von Features nicht mehr nach Dokument, sondern nach Monat gestaffelt wird.

## Document-feature matrix of: 5 documents, 5,162 features (23.0% sparse) and 2 docvars.
##           features
## docs       support ukip continues grow labour heartlands miliband scared leo mckinstry
##   april        220 1096        19   26    627         12      150     21   9         7
##   february      72  123         5    3    112          2       36      3   3         2
##   january        0    0         0    0      0          0        0      0   0         0
##   march        236  894        19   23    638          6      133     11  15         9
##   may          188 1493        17   20    767          9      261     22   2         2
## [ reached max_nfeat ... 5,152 more features ]

Da wir uns die Frequenz von Features später geordnet nach Zeit (d.h., beginnen mit Januar als erstem Monat und Mai als fünftem Monat des Untersuchungszeitraums) ausgeben lassen wollen, nutzen wir die numerische Gruppierungsvariable month_numeric, mit Hilfe derer uns der erste Monat automatisch als erstes und der letzte Monat automatisch als letztes angezeigt wird.

Dokument 1 entspricht also allen Texten, die im Januar publiziert wurden, Dokument 2 allen Texten, die im Februar publiziert wurden, etc.

## Document-feature matrix of: 5 documents, 5,162 features (23.0% sparse) and 2 docvars.
##     features
## docs support ukip continues grow labour heartlands miliband scared leo mckinstry
##    1       0    0         0    0      0          0        0      0   0         0
##    2      72  123         5    3    112          2       36      3   3         2
##    3     236  894        19   23    638          6      133     11  15         9
##    4     220 1096        19   26    627         12      150     21   9         7
##    5     188 1493        17   20    767          9      261     22   2         2
## [ reached max_nfeat ... 5,152 more features ]

Dann nutzen wir den textstat_frequency()-Befehl. Dieser gibt uns das absolute als auch relative Vorkommen unserer Features aus.

##     feature frequency rank docfreq group
## 1       two         4    1       1     1
## 2      much         3    2       1     1
## 3   kirsten         3    2       1     1
## 4   january         3    2       1     1
## 5     faces         3    2       1     1
## 6  thriller         3    2       1     1
## 7      make         2    7       1     1
## 8        us         2    7       1     1
## 9       may         2    7       1     1
## 10   really         2    7       1     1

Vielleicht wollen wir jetzt wissen, ob bestimmte Features über die Monate hinweg häufiger oder weniger häufig vorgekommen. Z.B. interessiert uns, ob das Wort immigration über die Monate hinweg häufiger oder weniger häufig vorgekommen ist.

Dazu lassen wir uns nur das Vorkommen eines Features, nämlich immigration über die Monate hinweg ausgeben:

##           feature frequency rank docfreq group
## 27    immigration         1   20       1     1
## 135   immigration       359    2       1     2
## 4502  immigration      1413    2       1     3
## 9625  immigration       833    7       1     4
## 14746 immigration       927    8       1     5

Schliesslich visualisieren wir die Entwicklung über Zeit, indem wir das absolute Vorkommen des Features mit dem ggplot-Package, einem R-Package für Visualisierungen, plotten.

Ich werde hier nicht genauer in das Package einführen - eine fantastische Einführung, wie ggplot-funktioniert liefert das folgende, online frei verfügbare Handbuch:

  • Chang, W. (2020). R Graphics Codebook, 2nd edition. Link

Das Package extrafont, das hier zusätzlich installiert und geladen wird, installiert über die loadfonts-Funktion zusätzliche Schriftarten, wenn wir unseren Graphen etwas individualisiert gestalten wollen - hier z.B., in dem wir nicht mit der Standard-Schrift, sondern der Garamond-Schriftart arbeiten wollen.

Was bedeutet der untenstehende Befehl?

Kurz zusammengefasst:

  • ggplot(plot, aes(x = group, y = frequency, group = 1)): R nutzt die Daten im dataframe-Objekt plot, um auf der x-Achse die Monate und auf der y-Achse das absolute Vorkommen des Features Immigration im jeweiligen Monat zu plotten. Dabei könnten wir auch mehrere Linien auf einmal plotten - dadurch, dass wir group hier auf 1 setzen, weisen wir R an, nur eine Variable als Linie zu visualisieren.
  • geom_line(): Wir weisen R an, die Entwicklung des Features über Zeit über eine Linie zu visualisieren. Size und color bestimmen hier, wie dick diese Linie sein soll und welche Farbe sie annehmen soll.
  • scale_x_discrete(“Monat”, labels = c(“Januar”, “Februar”, “März”, “April”, “Mai”)): Wie wir uns erinnern, hatten wir uns die Monate als Zahlenwerte von 1-5 ausgeben lassen. Damit jede/r Leser:in versteht, was mit diesen Werten gemeint ist, lassen wir uns die Werte von 1-5, die die x-Achse annehmen kann, mit den entsprechend zugehörigen Monaten ausgeben.
  • labs(y = “Absolutes Vorkommen des Features Immigration”, title = “Absolutes Vorkommen des Wortes Immigration über Zeit”): Wir weisen R an, welchen Titel die Y-Achse und der Graph insgesamt tragen soll.
  • theme(text=element_text(size=12, family=“Garamond”)): Wir weisen R an, uns sämtliche Text-Elemente in der Schriftart “Garamond” auszugeben.

Damit kreiern wir folgenden Graph:

##           feature frequency rank docfreq group
## 27    immigration         1   20       1     1
## 135   immigration       359    2       1     2
## 4502  immigration      1413    2       1     3
## 9625  immigration       833    7       1     4
## 14746 immigration       927    8       1     5

Wir sehen also, dass das Wort immigration in einigen Monaten häufiger vorkam als in anderen (hier: frequency).

Wir sehen aber auch, dass wir bei der Interpretation der absoluten Vorkommens dieses Features vorsichtig sein sollten.

Beispielweise könnte bei Blick auf die Ausgabe denken, dass Immigration im Januar fast nie ein Thema war.

Die niedrige Frequenz des Wortes ist aber einzig damit zu begründen, dass wir nur ein Dokument aus dem Monat Januar vorliegen haben:

## 
##    april february  january    march      may 
##      827      248        1      908      849

Hilfreicher ist die relative Frequenz des Features immigration. Wir untersuchen also: Wie oft kam das Wort Immigration über die Monate hinweg im Vergleich zu allen anderen Wörtern vor?

Quanteda bietet die Möglichkeit, über die dfm_weight()-Funktion die relative Prozentanzahl, mit der ein Feature im Verhältnis zu allen anderen Features vorkommt, auszugeben.

Diese Option ist wichtig und nötig, weil das absolute Vorkommen eines Features nur bedingt etwas über die Wichtigkeit dieses Features aussagt. Wenn, wie erwähnt, z.B. in manchen Gruppen, zwischen denen wir das Vorkommen eines Features vergleichen wollen, mehr Texte publiziert wurden, ist es schwer, diese Gruppen zu vergleichen.

Z.B.: Wenn in einem Monat 10 Artikel und im nächsten 100 publiziert wurden, kommt das Features immigration vielleicht im zweiten Monat absolut gesehen viel häufiger vor - aber nur, weil im Monat mehr Artikel publiziert wurden, in denen das Feature jeweils einmal nebenbei genannt wird. Es kann sein, dass im ersten Monat verhältnismässig mehr über Immigration in 10 Texten gesprochen wurde als im zweiten in 100 Texten. Deshalb sollten wir uns immer das relative Vorkommen eines Features, z.B. wie viel % aller Tokens das Features immigration einnimmt, anschauen:

##     feature  frequency rank docfreq group
## 1       two 0.02515723    1       1     1
## 2      much 0.01886792    2       1     1
## 3   kirsten 0.01886792    2       1     1
## 4   january 0.01886792    2       1     1
## 5     faces 0.01886792    2       1     1
## 6  thriller 0.01886792    2       1     1
## 7      make 0.01257862    7       1     1
## 8        us 0.01257862    7       1     1
## 9       may 0.01257862    7       1     1
## 10   really 0.01257862    7       1     1

Dann visualisieren wir diese relative Häufigkeit wieder:

##           feature   frequency rank docfreq group
## 27    immigration 0.006289308   20       1     1
## 135   immigration 0.007442111    2       1     2
## 4502  immigration 0.007941415    2       1     3
## 9625  immigration 0.005196020    7       1     4
## 14746 immigration 0.005385809    8       1     5

Vergleichen Sie beide Dateien, sehen Sie, dass sich beide Graphen unterscheiden.

12.3 Keywords-in-Context

Wir haben im Rahmen der Bereinigung viel über die Probleme gesprochen, die bag-of-words-Ansätze, durch die u.a. die Reihenfolge und der Kontext von Wörtern ignoriert wird, mit sich bringt.

Das gilt insbesondere für die Frage nach Beziehungen zwischen patterns - etwa der Frage danach, mit welchen Wörtern - negativ oder positiv - ein Akteur oder Thema bezeichnet wird.

Nehmen wir einmal an, wir wollen wissen, ob das Wort Immigration in unserem Korpus eher mit negativen oder mit eher positiven Wörtern beschrieben wird.

Um dies herauszufinden, können wir uns sogenannte Keywords-in-Context anschauen.

Keywords-in-Context beschreiben eine Methode, bei der wir nach einem bestimmten Schlüsselbegriff - etwa Immigration - suchen und uns n-beliebig viele Wörter vor oder nach diesem Schlüsselwört ausgeben lassen.

Nehmen wir einmal an, wir wollen uns die drei Features ausgeben lassen, die vor und nach dem Schlüsselwort Immigration stehen, um einen besseren Eindruck von Wörtern zu bekommen, mit denen Immigration beschrieben wird.

Der kwic()-Befehl gibt uns alle n Wörter aus, die vor und nach einem pattern im Text-String x stehen.

##                                                                                          
##  [text1, 371]        obsessed with mass | immigration | multi-cultural diversity european
##  [text2, 132] britains broken open-door | immigration | policy the disease-ridden        
##  [text2, 343]          past year calais | immigration | chief and deputy                 
##  [text2, 402]          seeking to evade | immigration | control they are                 
##  [text3, 130] britains broken open-door | immigration | policy the disease-ridden        
##  [text3, 353]          past year calais | immigration | chief and deputy                 
##  [text5, 157]        secure units under | immigration | laws at the                      
##  [text5, 241]          with the illegal | immigration | issue itself by                  
##  [text5, 386]            and deserve an | immigration | system that is                   
##  [text5, 399]             crack down on | immigration | offenders when we

Wenn wir eigene Diktionäre erstellen wollen - z.B. um zu analysieren, ob Immigration positiv oder negativ beschrieben wird, können wir mit Keywords-in-Context z.B. schauen, welche Begriffe rund um das Wort Immigration vorkommen.

Wir könnten Keywords-in-Context aber auch für erste Analysen nutzen. Z.B. könnten wir analysieren, ob rund um den Begriff Immigration das Wort Crime genannt wird, d.h., Immigration mit Kriminalität in Verbindung gebracht wird.

Unsere Frage: Wie oft wird das Thema Immigration mit Kriminalität in Verbindung gebracht?

Um das herauszufinden, lassen wir uns die drei Wörter vor dem pattern immigration, das pattern selbst und die drei Wörter nach dem pattern immigration als einen Text-String ausgeben. Der paste-Befehl fügt diese drei Variablen im Objekt kwic zusammen:

## [1] "obsessed with mass immigration multi-cultural diversity european"
## [2] "britains broken open-door immigration policy the disease-ridden" 
## [3] "past year calais immigration chief and deputy"                   
## [4] "seeking to evade immigration control they are"                   
## [5] "britains broken open-door immigration policy the disease-ridden"

Dann zählen wir ganz einfach aus, wie oft Kriminalität im Kontext von Immigration genannt wird:

## [1] 5

Insgesamt kommt das Wort Kriminalität also fünfmal im Kontext von Kriminalität vor - nicht besonders häufig.

12.4 Ko-Okkurenzen

Die vorherige Analyse hat bereits gezeigt, dass uns vielleicht noch andere Dinge interessieren - z.B., ob spezifische Wörter in einem Text zusammen vorkommen. Beispielsweise könnte uns interessieren, ob Texte, die über Immigration sprechen, ganz generell auch Kriminalität oder andere negative Begriffe erwähnen - egal ob im direkten Kontext von Immigration oder an anderen Stellen im Text.

Wir fragen uns also: Kommen die patterns immigration und crime gemeinsam in Texten vor?

Um diese Frage zu beantworten, müssen wir uns die Ko-Okkurrenz von Wörtern anschauen - d.h., ob zwei Wörter gemeinsam in einem Text vorkommen. Damit ist nicht gesagt, dass diese Wörter direkt nacheinander oder auch nur in Nähe voneinander vorkommen - sondern nur, dass beide in einem Text genannt werden.

Eine sogenannte co-occurrence-Matrix ist nicht unähnlich zu einer document-feature-Matrix. Die Spalten einer co-occurrence-Matrix bezeichnen Features, die Zeilen bezeichnen ebenso Features. Die Zellen zeigen an, wie häufig ein Feature zusammen mit einem anderen Feature in Texten vorkommt.

Schauen wir uns ein Beispiel an.

Wir erzeugen zunächst die co-occurrence-Matrix:

## Feature co-occurrence matrix of: 5,162 by 5,162 features.
##             features
## features     support ukip continues grow labour heartlands miliband scared leo mckinstry
##   support        330 1850        24   18   1062         37      198     24  14        12
##   ukip             0 9754        84   45   5467        164     1427    160  41        40
##   continues        0    0         2    3     45          2       13      1   6         5
##   grow             0    0         0    5     24          2       12      1   1         1
##   labour           0    0         0    0   3689        181     2277    107  37        37
##   heartlands       0    0         0    0      0          9       63      4   4         4
##   miliband         0    0         0    0      0          0      639     41  11        11
##   scared           0    0         0    0      0          0        0     27   1         1
##   leo              0    0         0    0      0          0        0      0   5        22
##   mckinstry        0    0         0    0      0          0        0      0   0         1
## [ reached max_feat ... 5,152 more features, reached max_nfeat ... 5,152 more features ]

Dann weisen wir R an, uns nur das Vorkommen des Wortes Immigration und anderer Wörter (hier eine Reihe möglicher negativer und positiver Begriffe) ausgeben zu lassen.

Wir reduzieren die Matrix mit dem Befehl fcm_select() also auf die Ko-Okkurrenz ausgewählter Begriffe - Immigration und eine Reihe positiver (chance, good) und negativer (crime, threat) Begriffe.

Dann visualisieren wir die Ko-Okkurrenz als Netzwerk, das visualisiert, wie oft Begriffe zusammen vorkommen.

Was zeigt uns dieses Netzwerk?

Begriffe werden durch Linien verbunden, wenn sie im gleichen Dokument vorkommen. Je öfter zwei Begriffe zusammen vorkommen, desto dicker sind diese Linien. Z.B. kommt das Wort “Immigration” sehr häufig mit dem Wort “Work” zusammen vor, wie man an den Linien sieht, die beide Begriffe verbinden. Weniger häufiger kommen die Wörter “Immigration” und “Crime” zusammen vor - etwas, das wir bereits durch unsere Analyse von Keywords-in-Context herausgefunden hatten-

Wenn wir diese Information nicht aus dem Netzwerk rauslesen wollen, können wir uns die Daten auch selbst anschauen. Um eine co-occurrence-Matrix zu inspizieren, bietet das quanteda-Package die nützliche Funktion convert(). Sehr viele quanteda-Objekte, inklusive der hier genutzten Matrix, lassen sich dadurch in Ihnen bereits bekannte Formate wie z.B. ein dataframe-Objekt umwandeln:

##         doc_id threat immigration illegal border control cost work immigrant good crime visa bad chance
## 1       threat     51         237       3     14      20   23   56        11   36    19    9   9     42
## 2  immigration      0        4556     601    692     860  682 1790       372  873   198  605 249    213
## 3      illegal      0           0     187    126      33   48   90       143   43    81   41  11      3
## 4       border      0           0       0    333     128   30  178        28   71    65   74  17      9
## 5      control      0           0       0      0     132   30  203        30   89    13   33  23     37
## 6         cost      0           0       0      0       0  230  131        22   76    15   18  20     16
## 7         work      0           0       0      0       0    0  826       202  359    60  219 125     77
## 8    immigrant      0           0       0      0       0    0    0        78   73    40   57  26     16
## 9         good      0           0       0      0       0    0    0         0  247    42  147 113     43
## 10       crime      0           0       0      0       0    0    0         0    0   236   20  23     21
## 11        visa      0           0       0      0       0    0    0         0    0     0  273  43      5
## 12         bad      0           0       0      0       0    0    0         0    0     0    0  36     18
## 13      chance      0           0       0      0       0    0    0         0    0     0    0   0     42

Dann könnten wir uns beispielsweise ausgeben lassen, ob das Wort Immigration häufiger mit dem Begriff work oder häufiger mit dem Begriff crime zusammen in einem Text vorkommt:

## numeric(0)
## numeric(0)

12.5 Diktionäranalyse

Wenden wir uns jetzt einem beliebten Verfahren der automatisierten Inhaltsanalyse zu: der Analyse via Diktionäre.

Diktionäre sind Wörterlisten. Auf Basis des manifesten Vorkommens gewisser Wörter - beispielsweise der Wörter “Krise”, “schlecht” und “verheerend” - wird auf das Vorkommen eines latenten Konstruktes - z.B. negatives Sentiment - geschlossen.

Sie haben im Seminar bereits die grundsätzliche Logik und Probleme des Verfahren kennengelernt. Aber wie setzt man dies in R um?

12.5.1 Erstellung eines Diktionärs

Wir unterscheiden im Seminar zwischen zwei Arten von Diktionären.

  • Off-the-Shelf-Diktionäre, d.h. vorgefertigte Wörterlisten, die oft für andere Textarten und Themenbereiche entwickelt wurden
  • Organische-Diktionären, d.h. eigens erstellte Wörterlisten

12.5.1.1 Off-the-Shelf Diktionär

Auf die Problematik der Validität sogenannter Off-the-shelf-Diktionären wurde im Seminar und den entsprechenden Literaturhinweisen, etwa Boukes et al., 2020, Chan et al., 2020 oder Stine, 2019, bereits hingewiesen.

Wenn Sie Off-the-shelf-Diktionäre verwenden, validieren Sie bitte sorgfältig, ob diese messen, was Sie meinen, zu messen.

Das quanteda-package enthält unter anderem das Off-the-Shelf-Diktionär Lexicoder Sentiment Dictionary zu negativem und positivem Sentiment von Young & Soroka, 2012a sowie Young & Soroka (2012b): Lexicoder Sentiment Dictionary.

Schauen wir uns das Diktionär einmal an:

## Dictionary object with 4 key entries.
## - [negative]:
##   - a lie, abandon*, abas*, abattoir*, abdicat*, aberra*, abhor*, abject*, abnormal*, abolish*, abominab*, abominat*, abrasiv*, absent*, abstrus*, absurd*, abus*, accident*, accost*, accursed* [ ... and 2,838 more ]
## - [positive]:
##   - ability*, abound*, absolv*, absorbent*, absorption*, abundanc*, abundant*, acced*, accentuat*, accept*, accessib*, acclaim*, acclamation*, accolad*, accommodat*, accomplish*, accord, accordan*, accorded*, accords [ ... and 1,689 more ]
## - [neg_positive]:
##   - best not, better not, no damag*, no no, not ability*, not able, not abound*, not absolv*, not absorbent*, not absorption*, not abundanc*, not abundant*, not acced*, not accentuat*, not accept*, not accessib*, not acclaim*, not acclamation*, not accolad*, not accommodat* [ ... and 1,701 more ]
## - [neg_negative]:
##   - not a lie, not abandon*, not abas*, not abattoir*, not abdicat*, not aberra*, not abhor*, not abject*, not abnormal*, not abolish*, not abominab*, not abominat*, not abrasiv*, not absent*, not abstrus*, not absurd*, not abus*, not accident*, not accost*, not accursed* [ ... and 2,840 more ]

Wir sehen, dass das Diktionär aus vier Key Entries besteht - hier die Konstrukte, die überprüft werden sollen. Für jedes dieser Konstrukte findet sich eine lange Wörterliste - die patterns, über deren Vorkommen wir Rückschlusse auf das Vorkommen des Konstruktes ziehen wollen.

Vielleicht wollen wir wissen, ob über Zeit mehr positives oder negatives Sentiment in UK-Nachrichten zum Thema Immigration vorkommt.

Wie wir bereits wissen, macht es oft wenig Sinn, sich das absolute Vorkommen von Features über Zeit ausgeben zu lassen. Denn: Das absolute Vorkommen ist auch davon abhängig, wie viele Texte je Gruppe publiziert wurden, etc.

Wir müssen unsere Texte also wieder normalisieren, um zu schauen, schauen wie viel Prozent aller Features in einem Monat negativ oder positiv waren.

Wir wenden drei Schritte an, um herauszufinden, wie oft ein Konstrukt - etwa positives oder negatives gesehen - relativ gesehen über verschiedene Monate hinweg vorkommt:

  1. Gruppierung
  2. Normalisierung
  3. Erfassung des Konstrukts mittels Diktionär

Dafür gruppieren wir als erstes unsere Features nach Monat, gewichten dann das Vorkommen jedes Features nach Monat und analysieren dann, wie oft Features vorkommen, die mit positivem oder negativem Sentiment verbunden werden:

## Document-feature matrix of: 5 documents, 2 features (0.0% sparse) and 2 docvars.
##     features
## docs   negative   positive
##    1 0.03144654 0.09433962
##    2 0.04910964 0.06921785
##    3 0.05530327 0.06704397
##    4 0.05786109 0.06326295
##    5 0.05799476 0.06017929

Wir sehen also, wie viele negative und positive Wörter über Zeit relativ gesehen in den Artikeln verwendet wurden.

Wir können uns diese Ausgabe auch visualisieren lassen. Dafür wandeln wir unsere gruppierte Document-feature-matrix über den convert-Befehl in ein dataframe-Objekt um.

Damit wir positives und negatives Sentiment getrennt visualisieren können, müssen wir unser dataframe-Objekt plot vom sogenannten wide-Format, bei dem alle Variablen als einzelne Spalten ausgeführt werden, zum long-Format, bei dem die Werte aller Variablen - negatives und positives Sentiment - in einer Spalte aufgeführt werden und eine weitere Gruppierungsvariable die jeweilige Variable kennzeichnet, transformieren.

Dafür benötigen wir das reshape-Package. Mit dem Befehl melt wandeln wir unsere Daten vom wide-Format zum long-Format um. Dabei müssen wir der Funktion anweisen, welche Variable unsere einzelne Beobachtung, d.h. hier den Monat der Beobachtung, kennzeichnet:

##    doc_id variable      value
## 1       1 negative 0.03144654
## 2       2 negative 0.04910964
## 3       3 negative 0.05530327
## 4       4 negative 0.05786109
## 5       5 negative 0.05799476
## 6       1 positive 0.09433962
## 7       2 positive 0.06921785
## 8       3 positive 0.06704397
## 9       4 positive 0.06326295
## 10      5 positive 0.06017929

Anschliessend visualisieren wir die Verteilung von positiven und negativen Features über Zeit:

Wir müssen hier wieder vorsichtig sein - denn unser Korpus aus dem Monat Januar enthält nur einen Artikel. Insgesamt scheint es aber so, dass negatives Sentiment über Zeit leicht zugenommen und positives Sentiment leicht abgenommen hat.

12.5.1.2 Organisches Diktionär

Ein besseres Vorgehen ist es oft, eigene Diktionäre zu entwicklen. Sogenannte organische Diktionäre bestehen aus eigens erstellten Wörterlisten s. etwa Muddiman et al. (2019).

Beispielsweise wollen Sie wissen, wie oft in Ihrem Korpus angst-induzierende Sprache vorkommt. Sie haben ein eigenes Diktionär entwickelt, dass aus Wörtern besteht, die angstinduzierende Sprache beschreiben.

Sie könnten den Befehl dictionary nutzen, um ein eigenes, organisches Diktionär im R-Environment zu erstellen.

## Dictionary object with 1 key entry.
## - [angst]:
##   - anxiety, anxious, afraid, crisis, terror, threat, carnage, disaster, horror, tear, cry, nightmare, kill, death, monster, defeat, crime, violence, violent

Dann nutzen wir die gleichen Logik wie zuvor, um uns das Vorkommen angst-induzierender Sprache über Zeit ausgeben zu lassen:

  • Wir gruppieren unsere document-feature-Matrix nach Monaten
  • Wir lassen uns das relative Vorkommen aller Features ausgeben
  • Wir suchen nur nach Features, die in unserem organischen Diktionär vorkommen
## Document-feature matrix of: 5 documents, 1 feature (20.0% sparse) and 2 docvars.
##     features
## docs       angst
##    1 0          
##    2 0.002010821
##    3 0.002197518
##    4 0.002794498
##    5 0.002521511

Dann wandeln wir unseren Data-Frame in long-Format um und visualisieren unsere Ergebnisse:

12.6 Take Aways

Vokabular:

  • Keywords-in-Context bzw. Keywords-in-Context-Analyse: Analyse, welche Wörter im Kontext eines Schlüsselworts vorkommen
  • Ko-Okkurrenzen bzw. Ko-Okkurrenzen-Analyse: Analyse, welche Wörter gemeinsam in einem Dokument vorkommen
  • Diktionär: Diktionäre sind Wörterlisten. Auf Basis des manifesten Vorkommens dieser Wörter wird auf das Vorkommen eines latenten Konstruktes - z.B. Sentiment - geschlossen.
  • Off-the-Shelf-Diktionäre: vorgefertigte Wörterlisten, die oft für andere Textarten und Themenbereiche entwickelt wurden
  • Organische-Diktionären: eigens erstellte Wörterlisten

Befehle:

  • Anzahl Dokumente & Features: ndoc(), nfeat()
  • Vorkommen von Features: featfreq(), topfeatures(), textstat_frequency(), dfm_weight(), textplot_wordcloud(), dfm_group()
  • Keywords-in-Context: kwic()
  • Ko-Okkurrenzen: fcm(), fcm_select(), textplot_network()
  • Umwandlung von quanteda-Formaten: convert()
  • Diktionär-Analyse: dictionary()

12.8 Benotete Aufgabe in R III

Achtung: Bei der nachfolgenden Aufgabe handelt es sich um die dritte benotete Aufgabe in R. D.h., die fristgerechte Abgabe dieser Aufgabe ist eine benotete Leistungsabgabe. Die Abgabe soll zum 14.12.2020 um 12 Uhr erfolgen.

Bitte bearbeiten Sie die Aufgabe in Gruppen von mind. 2 und max. 3 Personen.

Bitte nutzten Sie für die Abgabe Ihrer Lösungen das vorgegebene R-Template (via OLAT: Materialien / Templates/ Benotete Aufgabe in R_3.R).

Wir arbeiten für die Aufgabe wieder mit dem Textkorpus: speeches.rda

Sie finden den Korpus in OLAT (via: Materialien / Datensätze für R) mit dem Namen speeches.rda.

Bei diesen Dateien handelt es sich um “State of the Union Addresses” von US-Präsidenten seit 1790, die bereits als R-Environment abgespeichert wurde. Die Daten befinden sich in einem ähnlichen Format, wie Sie sie erhalten würden, wenn Sie ihre Text mit dem readtext-Package einlesen würden und zusätzlich noch einige document_level-Variablen bereits abgespeichert hätten.

Quelle der Daten: The American Presidency Project. Geladen via dem Quanteda-Corpus_Package.

12.8.1 Aufgabe 12.1

Laden Sie den Korpus. Lassen Sie sich nur die Reden der demokratischen und republikanischen Präsidenten ausgeben (“Democratic” oder “Republican” in der party-Variable). Was sind die 10 Top Features bei Reden demokratischer vs. republikanischer Präsidenten?

Hinweis: Sie brauchen hier und in späteren Aufgaben keine Bereinigungs-Schritte vornehmen. Wandeln Sie den Text einfach so, wie er vorliegt, um.

12.8.2 Aufgabe 12.2

Lassen Sie sich für den vollen Datensatz mit allen 241 Reden das relative Vorkommen der Features “threat” über die Jahre hinweg ausgeben.

12.8.3 Aufgabe 12.3.

Können Sie sich die Länge der Rede, d.h. die durchschnittliche Anzahl an Features je Rede, über die Jahre hinweg ausgeben lassen? Achten Sie darauf, dass es teils mehrere Reden je Jahr gibt. D.h., Sie müssen die durchschnittliche Anzahl an Features über verschiedene Reden hinweg je Jahr berechnen.

12.8.4 Aufgabe 12.4.

Visualisieren Sie die Ergebnisse aus Aufgabe 12.3. Welche Art der Visualisierung bzw. welchen Graphentyp Sie nutzen, ist egal. Wichtig ist nur, dass die x-Achse das Jahr der Rede und die y-Achse die durchschnittliche Anzahl an Wörtern der jeweiligen Rede(n) enthält.

Wenn Sie die Aufgabe 12.3 nicht lösen konnten, visualisieren Sie bitte einfach die Anzahl an Reden je Jahr. Wichtig ist dass, dass die x-Achse das Jahr der Rede und die y-Achse die Anzahl an Reden je Jahr enthält.

Die Lösungen finden Sie bei Lösungen zu Tutorial 12.

Wir machen weiter: mit [Tutorial 13: Unüberwachtes maschinelles Lernen: Topic Modeling]