Einführung in R

25.04.2019 - Valentin Gold - Reading time ~18 Minutes


Eine (kurze) Einführung in R und RStudio

Die quantitative Analyse von Textdaten setzt Kenntnisse einer Programmiersprache voraus. Im Seminar werden wir überwiegend mit R arbeiten. Diese Seite dient dazu, Ihnen die notwendigen Kenntnisse zu vermitteln, damit Sie eine eigene Fragestellung im Bereich quantitativer Textanalyse bearbeiten können. Die Überschrift dieser Seite beinhaltet bereits das Wort “kurz” – und genauso ist diese kurze Einführung zu verstehen: Viele interessante Hintergründe zur Programmierung in R und meines Erachtens nach für das Seminar nicht notwendige Schritte in R werden vernachlässigt. Es gibt eine ganze Reihe guter Einführungsbücher für R; viele davon sind in der SUB Göttingen verfügbar. Eine erfolgreiche Teilnahme am Seminar setzt Ihre Bereitschaft voraus, dass Sie die hier vermittelten Grundlagen der Programmierung in R eigenständig einüben, so dass wir uns in einem zweiten Schritt dann gemeinsam an die quantitative Textanalyse wagen können. Selbstverständlich gibt es im Rahmen des Seminars auch Zeit für Fragen (und Antworten); auch zu den Grundlagen zu R.

R und RStudio

R ist eine Programmiersprache und -umgebung für statistische Berechnungen und Grafiken. R basiert auf der Programmiersprache S und wurde Anfang der 1990er von Ross Ihaka und Robert Gentleman am Fachbereich Statistik der Universität Auckland, Neuseeland, entwickelt. R ist Open Source und Teil des GNU General Public License Projekts. Seit 1997 wird das R-Projekt von einem R Development Core Team betreut, das auch das größte Paketrepository auf dem Comprehensive R Archive Network (CRAN) betreut. Auf diesem Paketverzeichnis stehen derzeit über 14.000 Pakete zur Verfügung. Einige dieser Pakete werden wir hier im Seminar nutzen, z.B. für die Datenmanipulation tidyverse und für die quantitative Analyse von Textdaten quanteda und spacyR.

Im Seminar werden wir mit RStudio (https://www.rstudio.com/) arbeiten. RStudio ist eine integrierte Entwicklungsumgebung (IDE) für R und bietet viele nützliche Funktionen, die in der regulären Version von R nicht verfügbar sind. Einen Überblick über viele Funktionen liefert das Cheatsheet https://www.rstudio.com/resources/cheatsheets/#ide.

Funktionen der RStudio IDE, Quelle: https://www.rstudio.com/resources/cheatsheets/#ide

Figure 1: Funktionen der RStudio IDE, Quelle: https://www.rstudio.com/resources/cheatsheets/#ide

Grundsätzliches zu R

In R gibt es prinzipiell nur 2 Elemente: Objekte und Funktionen.

Um Berechnungen in R zu verstehen sind zwei Sätze hilfreich: Alles, was existiert, ist ein Objekt. Alles, was passiert, ist ein Funktionsaufruf. (John M. Chambers)

Objekte sind gespeicherte Elemente, z.B. Datensätze (oder in der Sprache von Tidyverse: Tibbles); Funktionen sind (statistische) Anwendungen und (mathematische) Verfahren, die auf die Objekte angewandt werden, z.B. die Berechnung des arithmetischen Mittelwertes oder – im Bereich der quantitativen Textanalyse – die automatische Extraktion von Themen.

Zu den grundsätzlichen Anwendungsmöglichkeiten habe ich Ihnen bereits in der ersten Sitzung ein Skript zur Verfügung gestellt. In diesem Skript wird u.a. gezeigt:

  • R als Taschenrechner, z.B. 2^3
  • Funktionen und ihre Argumente, z.B. log(x=10, base=10)
  • Fehler- und Warnmeldungen
  • Hilfeseite aufrufen, z.B. ?mean oder Befehl markieren und dann Taste F1 drücken
  • Nutzen des Zuweisungsoperators, z.B. num_objekt <- c(1, 2, 3, 4)
  • Vordefinierte Funktionen, z.B. letters und LETTERS
  • Gültige und ungültige Objektnamen, z.B. 1_objekt <- 42 (ungültig)
  • Objekttypen, d.h. numerisch, character, z.B. char_objekt <- c("wort1", "wort2", "wort3")
  • Objekttransformationen, d.h. von numerisch zu character oder vice versa, z.B. as.character(num_objekt)
  • Anwendung von (einfachen) Funktionen, z.B. mean(num_objekt) und range(num_objekt)
  • Extraktion spezifischer Werte, z.B. num_objekt[3]
  • Nutzung logischer Operanden, z.B. num_objekt[num_objekt > 2 | num_objekt < 1]
  • Vektoren, Listen, Matrizen, Dataframes
  • Angabe fehlender Werte, z.B. char_objekt <- c("wort1", "wort2", NA, NA, "wort5")
  • Extraktion fehlender Werte, z.B. char_objekt[!is.na(char_objekt)]
  • Sequenzen und Wiederholungen

Die Paketsammlung Tidyverse

Es gibt seit einigen Jahren eine Sammlung von Paketen, die alle eine ähnliche Philosophie verfolgen: tidyverse. Die Tidyverse-Pakete vereinfachen die Bearbeitung von Datensätzen enorm und sind im Vergleich zu anderen R-Dialekten relativ schnell zu erlernen. Daher werden wir uns im Seminar überwiegend mit diesen Pakete beschäftigen. Sie finden ein sehr gutes Einführungsbuch online: https://r4ds.had.co.nz/.

Die Pakete des Tidyverse, Quelle: https://www.tidyverse.org/

Figure 2: Die Pakete des Tidyverse, Quelle: https://www.tidyverse.org/

Alle Pakete aus dem CRAN Paketrepository haben ein Manual, in dem alle Befehle aufgelistet und beschrieben sind. Ebenso gibt es inzwischen für viele Pakete Vignetten, die eine praktische und angewandte Einführung in die wesentlichsten Paketfunktionen liefern. Diese Vignetten sind sehr hilfreich und in den allermeisten Fällen ist es wesentlich zielführender, sich die Vignetten durchzulesen als das Manual. Vignetten sind online verfügbar oder auch über die Kommandozeile in RStudio, z.B. vignette('tibble'). Wenn das Paket geladen ist, sollte unten rechts der Tab Help die Vignette anzeigen.

Vignette des Paketes Tibble

Figure 3: Vignette des Paketes Tibble

Hier folgt ein Überblick über die wesentlichsten Funktionen, die bei der Analyse von Textdaten häufig angewendet werden. Als Beispiel nehme ich die Plenarprotokolle des Bundestages der 18.Legislaturperiode. Die Daten wurden dem GermaParl Paket entnommen und in einen Tibble (Tidyverse Dataframe) konvertiert.

Laden des Datensatzes

Es gibt zwei Möglichkeiten, Daten in R bzw. RStudio bereit zu stellen: Laden und Importieren. Wenn ein Datensatz im R eigenen Format zur Verfügung steht, d.h. mit den Dateiendungen .RData, .Rda, oder .Rds, dann können Sie den Datensatz einfach über die Kommandozeile oder das Menü in RStudio laden. Das ist der einfachste Weg. Die meisten der Datensätze, die wir im Seminar nutzen werden, stehen bereits im R genuinen Format zur Verfügung, so dass es hier keine Probleme geben sollte. Alle anderen Datenformate lassen sich in R importieren, z.B. .csv, .txt, .pdf, .json, .xml, .xlsx, .dta, .html. Für die gängigen Textformate .csv und .txt steht ein Menü zur Verfügung; alle anderen Datenformate lassen sich über externe Pakete einlesen. Das kann aber relativ schnell relativ komplex werden, v.a. für den Import von (dynamischen) Webseiten. Dasselbe gilt für APIs: Es gibt viele Pakete, die für den Zugriff bestimmter APIs programmiert sind. So lassen sich z.B. auch Nachrichten auf Twitter oder Facebook einlesen.

RStudio Menü zum Importieren von Textdaten

Figure 4: RStudio Menü zum Importieren von Textdaten

Die Daten der 18.Legislaturperiode liegen bereits im R-genuinen Format .rda vor, so dass ein einfaches Laden ausreicht. Der Datensatz hat eine Größe von insgesamt 247.789 Beobachtungen, d.h. (unterbrochene) Reden und Zwischenrufe. Da wir mit dem Tidyverse arbeiten, muss zuerst das erforderliche Paket geladen werden. Das Paket Tidyverse bündelt verschiedene andere Pakete, z.B. tibble, dplyr, magrittr, ggplot2. Im WiSoRZ steht das Tidyverse nicht zur Verfügung, sondern nur die einzelnen Pakete. Bevor Sie die Pakete auf Ihrem eigenen Rechner laden können, müssen diese erst installiert werden. Hierfür einfach die Kommentarzeichen löschen.

# Pakete installieren (zu Hause)
#install.packages("tidyverse") #einfach das "#" am Anfang der Zeile löschen
#library(tidyverse)

# Pakete laden (im WiSoRZ)
library(tibble) 
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(magrittr)

Bevor Sie den Datensatz über die Kommandozeile laden, müssen Sie Ihr Heimatverzeichnis in R angeben. Alle Dateipfade müssen dann ausgehend von diesem Heimatverzeichnis spezifiziert werden. Es macht z.B. Sinn, die Daten in einem eigenen Unterverzeichnis zu speichern; ebenso die Skripte. Die Pfadangabe ../ geht ein Verzeichnis nach oben. Das Arbeitsverzeichnis lässt sich entweder direkt über die Kommandozeile setwd("absoluter/pfad/zum/ordner") als auch in RStudio über den Tab Files > More > Set As Working Directory setzen.

Setzen des Heimatverzeichnisses in RStudio

Figure 5: Setzen des Heimatverzeichnisses in RStudio

Bei mir sieht die Pfadangabe zum Laden der Datei wie folgt aus:

# Aufbereiteten Datensatz laden
load("../../../daten/polmineR/germaparl_session18.rda")

Sie können aber natürlich auch das Menü zum Laden des Datensatzes nutzen\(\ldots\)

Inspektion des Datensatzes

Ein wesentlicher und nicht zu vernachlässigender Teil der Datenanalyse ist die Inspektion des Datensatzes. Das Motto “Know your data” ist sprichwörtlich korrekt: Je besser Sie einen Datensatz kennen, umso einfacher und schneller können Sie Ihre Ergebnisse interpretieren. Sie können sogar ein Gefühl dafür entwickeln, ob die erzielten Ergebnisse stimmen können oder ob evtl. etwas fehlerhaft ist – die sog. “Face Validity”. Unterschätzen Sie das nicht: In vielen Fällen liegen Sie mit Ihrem Gefühl richtig und Sie können Aufbereitungs- und Analysefehler frühzeitig entdecken.

# Inspektion des Datensatzes
glimpse(session_18) #Funktion aus dem Tidyverse
## Observations: 247,789
## Variables: 17
## $ turn_id             <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13…
## $ lp                  <dbl> 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, …
## $ year                <dbl> 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, …
## $ session             <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ date                <date> 2013-10-22, 2013-10-22, 2013-10-22, 2013-10…
## $ speaker             <chr> "Volker Kauder", "Volker Kauder", "Volker Ka…
## $ interjection        <chr> "FALSE", "TRUE", "FALSE", "TRUE", "FALSE", "…
## $ party               <chr> "CDU", "CDU", "CDU", "CDU", "CDU", "CDU", "C…
## $ parliamentary_group <chr> "CDU/CSU", "CDU/CSU", "CDU/CSU", "CDU/CSU", …
## $ role                <chr> "mp", "mp", "mp", "mp", "mp", "mp", "mp", "m…
## $ agenda_item         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ agenda_item_type    <chr> "", "", "", "", "", "", "", "", "", "", "", …
## $ url                 <chr> "http://www.bundestag.de/blob/194766/23ded4b…
## $ src                 <chr> "txt", "txt", "txt", "txt", "txt", "txt", "t…
## $ lemma               <chr> "Herr Alterspräsident , ich schlagen im Name…
## $ pos                 <chr> "NN NN $, PPER VVFIN APPRART NN ART NN PPOSA…
## $ word                <chr> "Herr Alterspräsident, ich schlage im Namen …
str(session_18) #Base-R Funktion; siehe auch Tab "Environment" in RStudio oben rechts
## Classes 'tbl_df', 'tbl' and 'data.frame':    247789 obs. of  17 variables:
##  $ turn_id            : num  0 1 2 3 4 5 6 7 8 9 ...
##  $ lp                 : num  18 18 18 18 18 18 18 18 18 18 ...
##  $ year               : num  18 18 18 18 18 18 18 18 18 18 ...
##  $ session            : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ date               : Date, format: "2013-10-22" "2013-10-22" ...
##  $ speaker            : chr  "Volker Kauder" "Volker Kauder" "Volker Kauder" "Volker Kauder" ...
##  $ interjection       : chr  "FALSE" "TRUE" "FALSE" "TRUE" ...
##  $ party              : chr  "CDU" "CDU" "CDU" "CDU" ...
##  $ parliamentary_group: chr  "CDU/CSU" "CDU/CSU" "CDU/CSU" "CDU/CSU" ...
##  $ role               : chr  "mp" "mp" "mp" "mp" ...
##  $ agenda_item        : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ agenda_item_type   : chr  "" "" "" "" ...
##  $ url                : chr  "http://www.bundestag.de/blob/194766/23ded4ba56c8a9596cb9d24cc5f4e67b/18001-data.txt" "http://www.bundestag.de/blob/194766/23ded4ba56c8a9596cb9d24cc5f4e67b/18001-data.txt" "http://www.bundestag.de/blob/194766/23ded4ba56c8a9596cb9d24cc5f4e67b/18001-data.txt" "http://www.bundestag.de/blob/194766/23ded4ba56c8a9596cb9d24cc5f4e67b/18001-data.txt" ...
##  $ src                : chr  "txt" "txt" "txt" "txt" ...
##  $ lemma              : chr  "Herr Alterspräsident , ich schlagen im Name d CDU/CSU-Bundestagsfraktion unser Kollege Professor Dr. Norbert Lammert vor ." "#unknown# Beifall im ganz Haus #unknown#" "Alterspräsident Dr. Heinz Riesenhuber : mein Dame und Herr , Sie|sie haben d Vorschlag gehören . d abgeordnet D"| __truncated__ "#unknown# Heiterkeit #unknown#" ...
##  $ pos                : chr  "NN NN $, PPER VVFIN APPRART NN ART NN PPOSAT NN NN NN NE NE PTKVZ $." "TRUNC NN APPRART ADJA NN TRUNC" "NN NN NE NE $. PPOSAT NN KON NN $, PPER VAFIN ART NN VVFIN $. ART NN NN NE NE VAFIN VVPP VAPP $. APPR PPER VVFI"| __truncated__ "TRUNC NN TRUNC" ...
##  $ word               : chr  "Herr Alterspräsident, ich schlage im Namen der CDU/CSU-Bundestagsfraktion unseren Kollegen Professor Dr. Norbert Lammert vor." "(Beifall im ganzen Hause)" "Alterspräsident Dr. Heinz Riesenhuber: Meine Damen und Herren, Sie haben den Vorschlag gehört. Der Abgeordnete "| __truncated__ "(Heiterkeit)" ...
# View() öffnet den Datensatz in einer Excel-like Ansicht in RStudio
# die Ladezeit kann bei großen Datensätzen lang sein...
#View(session_18)

Darüber hinaus stehen Ihnen eine Reihe weiterer Funktionen zur Verfügung, z.B.

names(session_18) # Variablennamen
##  [1] "turn_id"             "lp"                  "year"               
##  [4] "session"             "date"                "speaker"            
##  [7] "interjection"        "party"               "parliamentary_group"
## [10] "role"                "agenda_item"         "agenda_item_type"   
## [13] "url"                 "src"                 "lemma"              
## [16] "pos"                 "word"
dim(session_18) # Dimensionen des Datensatzes (auch oben rechts ablesbar)
## [1] 247789     17
head(session_18) # Erste 6 Beobachtungen des Datensatzes
## # A tibble: 6 x 17
##   turn_id    lp  year session date       speaker interjection party
##     <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
## 1       0    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 2       1    18    18       1 2013-10-22 Volker… TRUE         CDU  
## 3       2    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 4       3    18    18       1 2013-10-22 Volker… TRUE         CDU  
## 5       4    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 6       5    18    18       1 2013-10-22 Volker… TRUE         CDU  
## # … with 9 more variables: parliamentary_group <chr>, role <chr>,
## #   agenda_item <dbl>, agenda_item_type <chr>, url <chr>, src <chr>,
## #   lemma <chr>, pos <chr>, word <chr>
tail(session_18) # Letzte 6 Beobachtungen des Datensatzes
## # A tibble: 6 x 17
##   turn_id    lp  year session date       speaker interjection party
##     <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
## 1  237242    18    18     210 2016-12-16 Helmut… FALSE        CDU  
## 2  237242    18    18     210 2016-12-16 Petra … FALSE        LINKE
## 3  237243    18    18     210 2016-12-16 Petra … TRUE         LINKE
## 4  237244    18    18     210 2016-12-16 Helmut… FALSE        CDU  
## 5  237245    18    18     210 2016-12-16 Helmut… TRUE         CDU  
## 6  237246    18    18     210 2016-12-16 Petra … FALSE        LINKE
## # … with 9 more variables: parliamentary_group <chr>, role <chr>,
## #   agenda_item <dbl>, agenda_item_type <chr>, url <chr>, src <chr>,
## #   lemma <chr>, pos <chr>, word <chr>

Da der Datensatz im Tidyverse Datenformat Tibble bereit gestellt wird, wird die Bildschirmausgabe optimiert und nur diejenigen Daten gezeigt, die auch Platz auf dem Bildschirm haben. Sollten Sie “nur” einen Dataframe haben, dann bricht die Anzeige um.

Die wichtigsten Befehle aus dem Paket dplyr

Das Paket dplyr stellt eine Reihe von Funktionen bereit, mit denen ein Datensatz vergleichsweise einfach geändert werden kann. Einen sehr guten Überblick über diese Funktionen findet sich auf dem online verfügbaren Cheatsheet: https://www.rstudio.com/resources/cheatsheets/#dplyr. Die wichtigsten Befehle sind hier auch noch einmal aufgeführt.

pull und select

# Auswahl von Variablen, z.B.
head( 
  pull(session_18, interjection), # Transformation in Vektor
  n = 30
) 
##  [1] "FALSE" "TRUE"  "FALSE" "TRUE"  "FALSE" "TRUE"  "FALSE" "TRUE" 
##  [9] "FALSE" "TRUE"  "FALSE" "TRUE"  "FALSE" "TRUE"  "FALSE" "TRUE" 
## [17] "FALSE" "TRUE"  "FALSE" "FALSE" "TRUE"  "FALSE" "FALSE" "TRUE" 
## [25] "FALSE" "TRUE"  "FALSE" "TRUE"  "FALSE" "TRUE"

select(session_18, year, date) # Keine Transformation
## # A tibble: 247,789 x 2
##     year date      
##    <dbl> <date>    
##  1    18 2013-10-22
##  2    18 2013-10-22
##  3    18 2013-10-22
##  4    18 2013-10-22
##  5    18 2013-10-22
##  6    18 2013-10-22
##  7    18 2013-10-22
##  8    18 2013-10-22
##  9    18 2013-10-22
## 10    18 2013-10-22
## # … with 247,779 more rows

filter, distinct, sample_frac und slice

# Auswahl von Beobachtungen, z.B. 
filter(session_18, party=="FDP" | party=="SPD") # Logische Bedingung
## # A tibble: 66,833 x 17
##    turn_id    lp  year session date       speaker interjection party
##      <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
##  1     124    18    18       1 2013-10-22 Thomas… FALSE        SPD  
##  2     125    18    18       1 2013-10-22 Thomas… TRUE         SPD  
##  3     126    18    18       1 2013-10-22 Thomas… FALSE        SPD  
##  4     127    18    18       1 2013-10-22 Thomas… TRUE         SPD  
##  5     128    18    18       1 2013-10-22 Thomas… FALSE        SPD  
##  6     129    18    18       1 2013-10-22 Thomas… TRUE         SPD  
##  7     130    18    18       1 2013-10-22 Thomas… FALSE        SPD  
##  8     131    18    18       1 2013-10-22 Thomas… TRUE         SPD  
##  9     132    18    18       1 2013-10-22 Thomas… FALSE        SPD  
## 10     133    18    18       1 2013-10-22 Thomas… TRUE         SPD  
## # … with 66,823 more rows, and 9 more variables:
## #   parliamentary_group <chr>, role <chr>, agenda_item <dbl>,
## #   agenda_item_type <chr>, url <chr>, src <chr>, lemma <chr>, pos <chr>,
## #   word <chr>
distinct(session_18, party) # Löschen mehrfach vorkommender Werte
## # A tibble: 7 x 1
##   party 
##   <chr> 
## 1 CDU   
## 2 LINKE 
## 3 SPD   
## 4 GRUENE
## 5 CSU   
## 6 FDP   
## 7 ""
sample_frac(session_18, size = 0.00001)
## # A tibble: 2 x 17
##   turn_id    lp  year session date       speaker interjection party
##     <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
## 1  106240    18    18      97 2015-03-26 Thomas… FALSE        CDU  
## 2  171226    18    18     153 2016-01-29 Karamb… FALSE        SPD  
## # … with 9 more variables: parliamentary_group <chr>, role <chr>,
## #   agenda_item <dbl>, agenda_item_type <chr>, url <chr>, src <chr>,
## #   lemma <chr>, pos <chr>, word <chr>
slice(session_18, 1000:1001)
## # A tibble: 2 x 17
##   turn_id    lp  year session date       speaker interjection party
##     <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
## 1     954    18    18       3 2013-11-28 Britta… FALSE        GRUE…
## 2     955    18    18       3 2013-11-28 Britta… TRUE         GRUE…
## # … with 9 more variables: parliamentary_group <chr>, role <chr>,
## #   agenda_item <dbl>, agenda_item_type <chr>, url <chr>, src <chr>,
## #   lemma <chr>, pos <chr>, word <chr>

summarise und count

summarise(session_18, max_id = max(turn_id)) # Abfrage nach höchstem Id-Wert
## # A tibble: 1 x 1
##   max_id
##    <dbl>
## 1 237246
count(session_18, parties = party) # Anzahl der Beobachtungen je Partei
## # A tibble: 7 x 2
##   parties     n
##   <chr>   <int>
## 1 ""        297
## 2 CDU     68977
## 3 CSU     25414
## 4 FDP        65
## 5 GRUENE  44437
## 6 LINKE   41831
## 7 SPD     66768

mutate

# (Re)Kodierung einer Variablen, z.B. 
mutate(session_18, description = "Plenarprotokolle 18. Legislaturperiode")
## # A tibble: 247,789 x 18
##    turn_id    lp  year session date       speaker interjection party
##      <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
##  1       0    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  2       1    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  3       2    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  4       3    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  5       4    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  6       5    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  7       6    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  8       7    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  9       8    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 10       9    18    18       1 2013-10-22 Volker… TRUE         CDU  
## # … with 247,779 more rows, and 10 more variables:
## #   parliamentary_group <chr>, role <chr>, agenda_item <dbl>,
## #   agenda_item_type <chr>, url <chr>, src <chr>, lemma <chr>, pos <chr>,
## #   word <chr>, description <chr>

case_when

mutate(session_18, speaker_lammert = case_when(
  speaker == "Norbert Lammert" ~ 1, 
  TRUE ~ NA_real_
))
## # A tibble: 247,789 x 18
##    turn_id    lp  year session date       speaker interjection party
##      <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
##  1       0    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  2       1    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  3       2    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  4       3    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  5       4    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  6       5    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  7       6    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  8       7    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  9       8    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 10       9    18    18       1 2013-10-22 Volker… TRUE         CDU  
## # … with 247,779 more rows, and 10 more variables:
## #   parliamentary_group <chr>, role <chr>, agenda_item <dbl>,
## #   agenda_item_type <chr>, url <chr>, src <chr>, lemma <chr>, pos <chr>,
## #   word <chr>, speaker_lammert <dbl>

group_by

# Gruppierung nach einer bestimmten Variable, z.B. 
group_by(session_18, party) # in der Ausgabe nicht direkt sichtbar!!
## # A tibble: 247,789 x 17
## # Groups:   party [7]
##    turn_id    lp  year session date       speaker interjection party
##      <dbl> <dbl> <dbl>   <dbl> <date>     <chr>   <chr>        <chr>
##  1       0    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  2       1    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  3       2    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  4       3    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  5       4    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  6       5    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  7       6    18    18       1 2013-10-22 Volker… FALSE        CDU  
##  8       7    18    18       1 2013-10-22 Volker… TRUE         CDU  
##  9       8    18    18       1 2013-10-22 Volker… FALSE        CDU  
## 10       9    18    18       1 2013-10-22 Volker… TRUE         CDU  
## # … with 247,779 more rows, and 9 more variables:
## #   parliamentary_group <chr>, role <chr>, agenda_item <dbl>,
## #   agenda_item_type <chr>, url <chr>, src <chr>, lemma <chr>, pos <chr>,
## #   word <chr>

Es gibt noch weitere nützliche Funktionen, die wir zum Teil im Verlauf des Seminars kennen lernen werden.

Die Macht des Pipens: magrittr

Die Vorzüge dieser Funktionen werden erst in Kombination mit dem Paket magrittr deutlich: Mit dem Symbol %>% können Sie einzelnen Schritte zu einer einzelnen Bearbeitungskette zusammenfügen, ohne die Ergebnisse einzelner Schritte zwischenspeichern zu müssen. Es gibt auch eine Reihe weiterer Pipe-Symbole, die auf der Webseite des Paketes gut dokumentiert sind: https://magrittr.tidyverse.org/.

Logo magrittr, Quelle: https://magrittr.tidyverse.org/

Figure 6: Logo magrittr, Quelle: https://magrittr.tidyverse.org/

In der folgenden Analyse führe ich bereits einen neuen und für Sie wahrscheinlich bisher unbekannten Befehl ein: str_count. Diese Funktion aus dem Paket stringr werden wir uns im Verlauf des Seminars noch genauer anschauen – in der Sitzung zu regulären Ausdrücken.

library(stringr)
session_18 %>% 
  mutate(no_words = str_count(word, pattern="\\S+")) %>% # Anzahl der Wörter
  group_by(party) %>% # Gruppierung nach Partei
  filter(interjection == FALSE) %>% # Herausnahme von Zwischenrufen
  filter(role != "presidency") %>% # Herausnahme des Parlamentspräsidenten
  summarise(freq_words = sum(no_words)) %>% # Summe der Wörter
  mutate(perc_words = freq_words / sum(freq_words)) %>% # Anteil an Gesamtzahl der Wörter
  arrange(desc(freq_words)) # Sortierung absteigend
## # A tibble: 7 x 3
##   party  freq_words perc_words
##   <chr>       <int>      <dbl>
## 1 CDU       3346830   0.306   
## 2 SPD       3093834   0.283   
## 3 GRUENE    1751146   0.160   
## 4 LINKE     1578372   0.144   
## 5 CSU       1127274   0.103   
## 6 ""          20005   0.00183 
## 7 FDP          6277   0.000575

Wir können nicht nur die Anzahl der Wörter zählen, sondern auch die Anzahl spezifischer Wörter (hier: “Lammert”). (Evtl. müsste man noch für die Gesamtzahl der Wörter kontrollieren, damit man ein zuverlässiges Abbild der Worthäufigkeiten bekommt.)

session_18 %>% 
  mutate(no_words = str_count(word, pattern="Lammert")) %>% # Anzahl der spezifischen Wörter
  group_by(party) %>% 
  summarise(freq_fluechtling = sum(no_words)) %>% 
  arrange(desc(freq_fluechtling))
## # A tibble: 7 x 2
##   party  freq_fluechtling
##   <chr>             <int>
## 1 CDU                  80
## 2 SPD                  69
## 3 GRUENE               42
## 4 LINKE                39
## 5 CSU                  22
## 6 ""                    0
## 7 FDP                   0

Jetzt kann es dann endlich losgehen\(\ldots\)