Inhaltsanalysen sind eine zentrale empirische Methode in der Kommunikationswissenschaft, um systematisch Texte zu untersuchen, oft in Form von journalistischen Artikeln, Interviews oder Social Media Posts. Dieses Tutorial bietet Ihnen eine Einführung in die Inhaltsanalyse, indem es die wichtigsten Schritte erklärt – von der Entwicklung eines Kategoriensystems und Codebuchs bis hin zur Codierung von Texten und Berechnung der Intercoderreliabilität mithilfe von R.
Entwicklung eines Kategoriensystems und Codebuchs
Ein gut strukturiertes Kategoriensystem und ein detailliertes Codebuch sind entscheidend für die Durchführung einer Inhaltsanalyse, da sie die Reproduzierbarkeit der Analyse gewährleisten. Kategorien sollten klar definiert und eng an der Forschungsfrage ausgerichtet sein. Es ist wichtig, detaillierte Beschreibungen und Beispiele für jede Kategorie zu erstellen, damit diese in den Daten identifiziert und codiert werden können. Das Codebuch sollte diese Anweisungen für die Codierer ausführlich bieten. Lassen Sie uns das am Beispiel des Datensatzes aus tidycomm fbposts
veranschaulichen, wie ein solches Codebuch aussehen könnte:
Variable | Bescheibung | Wertebereich | Codes/ID |
---|---|---|---|
post_id | Unique ID of the coded Facebook post | NUMERIC | 1,2,3 … |
coder_id | ID of the coder | NUMERIC | 1= Coder 1 2= Coder 2 3= Coder 3 4= Coder 4 5= Coder 5 6= Coder 6 |
type | Type of the Facebook post | CATEGORICAL | „link“, „photo“, „status“, „video“ |
n_pictures | Number of pictures attached to the post, ranges from 0 to 6 | NUMERIC | 0,1,2… |
pop_elite | Populism indicator; aims to answer the research question: Does the post attack elites? | CATEGORICAL | 0 = no attacks on elites 1 = attacks political actors 2 = attacks public administration actors 3 = attacks economic actors 4 = attacks media actors/journalists 9 = attacks other elites |
pop_people | Populism indicator; aims to answer the research question: Does the post refer to ‚the people‘? | BINARY | 0 = does not refer to ‚the people‘ 1 = refers to ‚the people‘ |
pop_othering | Populism indicator; aims to answer the research question: Does the post attack ‚others‘? | CATEGORICAL | 0 = no attacks on ‚others‘ 1 = attacks other cultures 2 = attacks other political stances 3 = attacks other ‚others‘ |
Es ist wichtig anzumerken, dass die Kategorien normalerweise noch detaillierter beschrieben werden, um Missverständnisse unter den Codierern zu vermeiden. In der Regel werden auch Beispiele anhand des Samples im Codebuch gegeben und verdeutlicht, damit die Codierer eine klare Orientierung haben.
Codierung von Texten
Codierung von Texten in Excel
Texte können manuell in Excel codiert und als CSV- oder XLSX- Datei gespeichert werden. Bei der Erstellung einer Tabelle sollten Sie Spalten für jede Variable in Ihrem Codebuch definieren. Lassen Sie uns das an dem vorherigen Beispiel mit den Codierungen aus fbposts
schauen:
Nachdem Sie alle Texte codiert haben, können Sie diese speichern und in R für die weitere statistische Analyse mit der read.csv/read.xlsx
einlesen.
Befehl:
# Einlesen einer CSV-Datei in R
library(tidyverse)
data <- read.csv("path/to/your/file.csv")
data %>% head()
Codierung von Texten mit R
handcodeR
handcodeR
(Isermann, 2023) ist ein Paket für R, das speziell für die manuelle Codierung von Texten entwickelt wurde. Es ermöglicht Ihnen, Ihre Textdaten strukturiert zu codieren und diese Codierungen direkt in einer einheitlichen Umgebung zu verwalten und zu analysieren. Um das Paket handcodeR
zu installieren, verwenden Sie:
Befehl:
install.packages("handcodeR", force = TRUE)
Die Hauptfunktion des Pakets is handcode()
. Diese Funktion nimmt entweder einen Vektor von Texten und bis zu sechs benannte Zeichenvektoren mit Klassifikationskategorien oder ein bereits durch handcode()
initialisiertes Dataframe als Eingabe. Die Funktion ermöglicht es Benutzer:innen, Texte mithilfe der vordefinierten Kategorien in einer interaktiven Shiny-App zu annotieren und gibt ein Dataframe der Texte mit den annotierten Anmerkungen zurück.
Um die Nutzung von handcodeR
zu demonstrieren, erstellen wir einen Beispiel-Post auf Facebook und codieren diese mit den Funktionen des Pakets. Dabei orientieren wir uns an den Kategorien vom fbposts
-Datensatz.
Befehl:
# Beispiel-Post
post_text <- c(
"Politicians must be held accountable for their actions. It’s time to address how economic elites are exploiting the system for their own benefit, manipulating the truth through media to serve their interests. We must protect our cultural heritage from these external threats and recognize that the public administration is failing to serve the people. Our voices matter, and it’s time for change!"
)
Wir teilen den Post in einzelne Sätze auf, um die Codierung zu erleichtern. Dies wird durch die Funktion str_split
aus dem Paket stringr
erreicht.
# Aufteilen des Posts in einzelne Sätze
# install.packages("stringr") # nur das erste Mal nötig
library(stringr)
sentences_post <- unlist(str_split(post_text, pattern = "(?<=(?<!Mr)[\\.!?])\\s"))
str_split
teilt den Text basierend auf Satzendezeichen (.
oder !
oder ?
), gefolgt von einem Leerzeichen, während unlist
verwendet wird, um die Liste der Sätze in einen einfachen Vektor zu konvertieren.
Wir verwenden die Funktion handcode()
, um die Sätze des Posts zu codieren. Die Codierung basiert auf den Variablen pop_elite
, pop_poeple
und pop_othering
.
Befehl:
# Codierung erstellen
annotated <- handcode(data = post_texts,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"))
Ausgabe:
Zusätzlich können wir die Option context = TRUE
verwenden, um den aktuellen Satz zusammen mit den vorhergehenden und nachfolgenden Sätzen für ein kontextuelles Verständnis anzuzeigen.
Befehl:
annotated <- handcode(data = sentences_post,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"),
context = TRUE)
Ausgabe:
Sie können den Annotationsprozess jederzeit stoppen, indem Sie auf „Save and exit“ klicken. Danach wird die App geschlossen und die Funktion gibt einen Dataframe mit Ihren Texten und Anmerkungen zurück.
Ausgabe:
Um den Annotationsprozess später wieder aufzunehmen, verwenden Sie den zurückgegebenen Dataframe der letzten Ausführung von handcode()
als Eingabe für einen neuen handcode()
-Befehl. Standardmäßig setzt die Funktion die Annotation beim ersten noch nicht annotierten Text fort.
Befehl:
annotated <- handcode(data = annotated,
context = TRUE)
Ausgabe:
Um den Klassifizierungsprozess noch mehr zu vereinfachen, nutzt handcode()
die Tastenkombinationen: Leertaste für „zurück“ und Enter für „weiter“. Bereits kodierte Zeilen zeigen die vorherige Kodierung an, während neue Zeilen leer bleiben. Erreicht man die letzte Zeile, speichert die „Next“-Taste automatisch die Daten und schließt die Shiny-App.
Erweiterte Optionen
Standardmäßig beginnt handcode()
die Codierung bei der ersten Zeile in den Eingabedaten, die noch nicht annotiert wurde. Mit der Option start
können Sie jedoch festlegen, ab welcher Beobachtung der Codierungsprozess beginnen soll, zum Beispiel ab der dritten Zeile.
Befehl:
annotated <- handcode(data = sentences_post,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"),
start = 3)
Ausgabe:
Falls sich nicht annotierte Zeilen zwischen bereits kodierten Zeilen befinden, können Sie start = "all empty"
verwenden, um alle noch nicht kodierten Zeilen in der Reihenfolge, in der sie erscheinen, zu annotieren.
Befehl:
annotated <- handcode(data = sentences_post,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"),
start = "all_empty")
Ausgabe:
Es kann Situationen geben, in denen es sinnvoll ist, Texte in zufälliger Reihenfolge anzuzeigen, um sicherzustellen, dass der Kontext eines Textes innerhalb des größeren Textkörpers die Annotationen nicht beeinflusst. Um die Anzeigereihenfolge der Texte zu randomisieren, können Sie die Option randomize = TRUE
verwenden. Dies hat jedoch keinen Einfluss auf die Reihenfolge, in der die Texte im finalen Output sortiert werden.
Befehl:
annotated <- handcode(data = sentences_post,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"),
randomize = TRUE)
Ausgabe:
Standardmäßig zeigt handcode()
die fehlende Kategorie „Not applicable“ an. Wenn Sie eine andere oder mehrere fehlende Kategorien anzeigen möchten, können Sie einen Zeichenvektor mit den gewünschten Kategorien angeben. Die fehlende Kategorien werden automatisch in Grau dargestellt.
Befehl:
annotated <- handcode(data = sentences_post,
pop_elite = c("No attacks on elites", "Attacks political actors", "Attacks public administration actors", "Attacks economic actors", "Attacks media actors/journalists", "Attacks other elites"),
pop_people = c("Does not refer to 'the people'", "Refers to 'the people'"),
pop_othering = c("No attacks on 'others'", "Attacks other cultures", "Attacks other political stances", "Attacks other 'others'"),
missing = c("Trifft nicht zu", "Unentschieden"))
Ausgabe:
In der R-Ausgabe werden die fehlende Kategorien mit führenden und nachfolgenden Unterstrichen (_) gekennzeichnet:
Codierung von Texten mit SoSci Survey
Eine Alternative zur Codierung mit handcodeR oder Excel ist die Nutzung von SoSci Survey, die durch die Erstellung einer Selbstbefragung auch für Inhaltsanalysen verwendet werden kann. Die Fragen und Kategorien, die Sie erstellen und danach beantworten, orientieren sich nochmals an Ihrer zentralen Forschungsfrage.
SoSci Survey bietet den Vorteil, dass Sie umfangreiche Definitionen und Ankerbeispiele auf derselben Seite platzieren können, was den Codierungsprozess erheblich erleichtert. Zudem ist die Filterführung sehr intuitiv, insbesondere wenn die Codierung einer Kategorie das Nicht-Codieren anderer Kategorien nach sich zieht.
Sie können eine Selbstbefragung gestalten, indem Sie im Menü links oben unter “Fragenkatalog” auf “Rubriken” klicken, um neue Fragen zu erstellen und diese inhaltlich zu ordnen:
Für Antwortmöglichkeiten haben Sie verschiedene Optionen wie z.B. Auswahlfragen, Texteingaben, Bewertungen usw. Sie können auch detaillierte Beschreibungen der Kategorien einfügen, um den Codierern klare Anweisungen zu geben:
Danach gehen Sie auf “Fragebogen zusammenlegen”, wo Sie Ihre Fragen anordnen und ihre Darstellung in der Vorschau überprüfen können:
Vorschau-Fenster:
Im Vergleich zu handcodeR ist jedoch ein Nachteil, dass die zu annotierenden Texte in SoSci Survey nicht permanent sichtbar sind. Daher kann es hilfreich sein, den Text vor Beginn der Codierung zu kopieren, um am Ende noch einmal zu überprüfen, ob den richtigen Text mit der richtigen ID analysiert wurde. Dazu können Sie eine entsprechende Frage/Kategorie hinzufügen:
Weitere Informationen zur Erstellung von Fragebögen finden Sie auf der Website von SoSci Survey.
Berechnung der Intercoderreliabilität
Nachdem Sie den Codierungsprozess abgeschlossen haben, ist es wichtig, die Intercoderreliabilität zu berechnen, um die Übereinstimmung zwischen verschiedenen Codierern zu bewerten. Wir haben bereits ein existierendes Kompendium zum Thema. Hier ist jedoch noch einmal die Funktion zur Berechnung der Intercoderreliabilität in R anhand des Datensatzes fbposts
aus dem Paket tidycomm
.
Befehl:
# Laden des Pakets tidycomm
library(tidycomm)
# Laden des fbposts-Datensatzes
fbposts <- tidycomm::fbposts
# Berechnung der Intercoderreliabilität
fbposts %>% test_icr(post_id, coder_id)
Ausgabe:
# A tibble: 5 × 8
Variable n_Units n_Coders n_Categories Level Agreement Holstis_CR Krippendorffs_Alpha
* <chr> <int> <int> <int> <chr> <dbl> <dbl> <dbl>
1 type 45 6 4 nominal 1 1 1
2 n_pictures 45 6 7 nominal 0.822 0.930 0.880
3 pop_elite 45 6 6 nominal 0.733 0.861 0.339
4 pop_people 45 6 2 nominal 0.778 0.916 0.287
5 pop_othering 45 6 4 nominal 0.867 0.945 0.566
Die Kennzahlen geben Aufschluss darüber, wie konsistent die Codierer:innen die Daten kodiert haben. Hohe Werte bei Agreement, Holsti’s CR und Krippendorff’s Alpha deuten auf eine hohe Übereinstimmung und damit auf eine hohe Reliabilität der Codierungen hin. Hier ist ein Beispielbericht nach Kategorien:
„Wir testeten die Intercoder-Reliabilität für fünf Variablen, indem jeweils 45 Facebook-Posts von sechs Codierer:innen codiert wurden. Für die formale Kategorie des Typs des Facebook-Beitrags (type) erreichten wir ein perfektes Krippendorffs Alpha von eins. Auch die Anzahl der Bilder, die dem Beitrag angehängt sind (n_Bilder) wurde in hinreichender Übereinstimmung erfasst (α=0,880). Allerdings erreichten wir mit Krippendorffs Alpha keine befriedigende Reliabilität für die Populismus-Indikatoren (αpop_elite=0,339; αpop_people=0,287; αpop_othering=0,566), das Kategoriensystem musste folglich in einem zweiten Schritt geschärft werden.“
Referenzen
Isermann, Lukas. (2023). handcodeR: Text annotation app. R package version 0.1.2. http://doi.org/10.5281/zenodo.8075100.