# Pakete laden
library(quanteda)
library(tidyverse)
# Daten einlesen
bs_posts <- read.csv("./data/bluesky_data.csv") # Dateipfad ggf. anpassen
# Korpus erstellen
bluesky_corpus <- bs_posts %>%
distinct(uri, .keep_all = TRUE) %>% # jeder Post sollte nur einmal im Korpus vorkommen
filter(is_reskeet == FALSE) %>% # keine Reposts
select(uri, cid,
author_handle, author_name,
indexed_at, reply_count, repost_count,
like_count, quote_count,
is_reskeet,
text) %>%
corpus(docid_field = "uri",
text_field = "text")
# Tokenisierung & Bereinigung
tokens_bluesky <- tokens(bluesky_corpus,
remove_punct = TRUE,
remove_symbols = TRUE,
remove_numbers = TRUE,
remove_url = TRUE)
# Kleinschreibung & Stoppwörter
tokens_bluesky <- tokens_bluesky %>%
tokens_tolower() %>% # Kleinschreibung
tokens_remove(stopwords("de")) %>% # Entfernung von deutschen Stoppwörtern
tokens_remove("dass") # Entfernung von "dass"17 Sentiment-Analyse und diktionärbasierte Ansätze
Eine in der Analyse von Social-Media-Daten sehr häufig genutzte Methode ist die Sentiment-Analyse. Hierbei wird versucht, die Stimmung oder Emotion in einem Text zu bestimmen, z.B. ob ein Post oder Kommentar positiv, negativ oder neutral ist. Bei der Sentiment-Analyse kommen zumeist sogenannte Diktionäre (dictionaries) zum Einsatz kommen. Diese können aber auch genutzt werden, um andere Konstrukte zu messen wie z.B. Populismus.
17.1 Setup
Wie immer müssen wir zunächst die benötigten Pakete laden, die Daten importieren und diese aufbereiten. Wir nutzen in diesem Abschnitt nur Bluesky-Daten.
Wichtig: Bei der Sentiment-Analyse arbeiten wir mit den Tokens. D.h. wir müssen keine DFM erstellen.
Zur Erinnerung: Die Aufbereitung der Daten wird in Kapitel 15 beschrieben. Eine ausführliche Beschreibung zur Sammlung der Daten von Bluesky findet sich in Kapitel 11. Ein Beispiel-Skript zur Sammlung solcher Daten ist im Skript collect_data.R zu finden.
17.2 Sentiment-Analyse
Wie so oft gibt es für die Sentiment-Analyse viele verschiedene Ansätze, Methoden und Pakete. in R Die Auswahl sollte von der jeweiligen Fragestellung und der Art der Daten abhängen. Ein wichtiger Faktor ist dabei insb. auch die Sprache, in der die Daten vorliegen (siehe hierzu auch die Infobox “Mehrsprachige Daten” in Kapitel 16).
17.2.1 Sentiment-Analyse mit quanteda
Auch für die Sentiment-Analyse gibt es ein Erweiterungspaket für quanteda namens quanteda.sentiment. Dieses bietet eine Reihe von Optionen für unterschiedliche Arten der Sentimentanalyse sowie verschiedene Sprachen. Das das Paket (noch) nicht auf CRAN zu finden ist, müssen wir es von GitHub installieren.
remotes::install_github("quanteda/quanteda.sentiment")library(quanteda.sentiment)quanteda.sentiment bietet verschiedene Diktionäre für die Setntimen-Analyse. Das ReadMe im GitHub-Repository zum Paket bietet eine Übersicht. Neben den Sprachen, die diese abdecken, unterscheiden sich die Diktionäre auch darin, ob sie Polarität (polarity) und/oder Valenz (valence) für die Zuweisung von Sentiment Scores nutzen. Polarität ist eine Kategorie von zwei „Polen“ (wie negativ und positiv), während Valenz ein numerisches Gewicht ist.
Im nachfolgenden Beispiel nutzen wir Diktionär für Sentiment in deutschen politischen Texten von Rauh (2018).
dfm_de_rauh <- dfm(tokens_lookup(tokens_bluesky,
dictionary = data_dictionary_Rauh))Um das Ergebnis wieder mit den Daten zu verbinden, müssen wir die DFM erst in einen data.frame umwandeln und diesen dann mit den ursprünglichen Daten zusammenführen. Für den zweiten Schritt ist ein sogenannter “Join” nötig. Für die Verknüpfung mehrerer Data Frames bietet das Paket dplyr zahlreiche Funktionen (siehe hierzu auch Kapitel 9.4).
results_rauh <- convert(dfm_de_rauh, to = "data.frame") %>% # Umwandlung der DFM in einen data.frame
mutate(net_sentiment = (positive + neg_negative) - (negative + neg_positive)) # Berechnung eines Nettosentiment-Scores
glimpse(results_rauh)Rows: 2,555
Columns: 6
$ doc_id <chr> "at://did:plc:hngkefcientj2tq2gnspgfol/app.bsky.feed.pos…
$ neg_negative <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ neg_positive <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ negative <dbl> 3, 0, 1, 1, 1, 4, 2, 4, 2, 4, 1, 1, 1, 0, 4, 0, 2, 5, 0,…
$ positive <dbl> 6, 2, 1, 9, 4, 6, 3, 4, 1, 5, 0, 3, 1, 5, 0, 0, 2, 1, 3,…
$ net_sentiment <dbl> 3, 2, 0, 8, 3, 2, 1, 0, -1, 1, -1, 2, 0, 5, -4, 0, 0, -4…
Das Diktionär von Rauh bietet neben den Kategorien “positive” und “negative” auch die Kategorien “neg_positive” und “neg_negative”. Diese beziehen sich auf Negationen. Aus diesen vier Variablen berechnen wir hier Nettosentiment-Score für jeden Post. Diese Daten können wir nun mit den ursprünglichen Daten zu den Posts verknüpfen.
NB: Der resultierende Datensatz hat weniger Zeilen als die ursprünglichen Daten, da nicht alle Posts Wörter enthalten, die im Diktionär von Rauh vorkommen.
results_rauh <- results_rauh %>%
left_join(bs_posts, by = c("doc_id" = "uri"))Nun können wir uns z.B. die Posts mit den höchsten oder den niedrigesten Nettosentiment-Scores anschauen.
results_rauh %>% # Positivste Posts
arrange(desc(net_sentiment)) %>%
select(text, net_sentiment, author_handle) %>%
head(10) text
1 Herzlichen Glückwunsch an Yasmin Fahimi zur Wiederwahl als Vorsitzende des #DGB – und zu diesem starken Ergebnis! Viel Erfolg für den wichtigen Einsatz für gute Arbeit, soziale Gerechtigkeit und starken Zusammenhalt. Auf gute Zusammenarbeit weiterhin!\n\nwww.handelsblatt.com/politik/deut...
2 Wir wollen das Leben bezahlbar machen. Natur und Klima schützen. Die Wirtschaft stärken und nachhaltige Jobs schaffen. Frieden in Freiheit sichern und Vielfalt. Wir wollen, dass unser Land einfach funktioniert. Eine gute Zukunft für alle Kinder. #ZusammenWachsen\n\nwww.gruene.de/artikel/zusa...
3 Auch wenn noch nicht alle Stimmbezirke ausgezählt sind: Mehr als 40 Prozent Erststimmen sind ein tolles Ergebnis, über das ich mich riesig freue. Ganz herzlichen Dank allen, die mir Ihr Vertrauen geschenkt haben, und den vielen Wahlkämpferinnen und Wahlkämpfern für Euren großartigen Einsatz!
4 Weihnachten erinnert uns daran, wie wichtig Gemeinschaft, Nähe und Hoffnung sind. Gerade in herausfordernden Zeiten zählt dieser Zusammenhalt besonders. Ich wünsche Euch allen frohe Weihnachten und ein besinnliches Fest mit Euren Liebsten 🎄
5 Mit herzlichen Grüßen an all diejenigen, die Lust haben mitzumachen –\n\nbeim Einsatz für Klimaschutz, Vielfalt, Gleichberechtigung, eine moderne Wirtschaft, ein Leben, das bezahlbar ist & ein Land, das einfach funktioniert.\n\nLiebe Grüße auch an @britta-hasselmann.de beim DFB-Pokalfinale! 😎\n\n#ldknrw25
6 Unser Ziel ist es, die Wettbewerbsfähigkeit unserer Wirtschaft zu stärken und nachhaltige Investitionen zu fördern. Dieser Erfolg im Strompreisbereich ist ein Schritt in die richtige Richtung, um unsere Wirtschaft weiter zu stärken.
7 Hervorragende Initiative von Friedrich Merz. Das eingefrorene 🇷🇺 Vermögen zu nutzen, um €140 Mrd. für die Verteidigung der Ukraine zu mobilisieren, ist moralisch richtig & strategisch geboten. Es würde die Sicherheit Europas substanziell stärken.\nwww.ft.com/content/3aac...
8 43,82 Prozent sind es geworden. Wie ihr seht, freuen wir uns alle riesig über dieses tolle Ergebnis. Ganz herzlichen Dank an alle Wählerinnen & Wähler für das große Vertrauen! Jetzt heißt es anpacken - für unsere Region, für Deutschland & ein sicheres Europa!
9 Nichts von den US-Ankündigungen ist besonders überraschend. Aber sie machen einmal mehr deutlich, dass Europa seine Sicherheit selbst organisieren muss, wenn es bestehen will. Die Wiederherstellung von Sicherheit muss unbedingte Priorität der nächsten Bundesregierung sein.
10 Herzlichen Glückwunsch liebe Reem Alabali-Radovan zu Deiner neuen Aufgabe! Du übernimmst ein starkes Team und große Aufgaben: Globale Verantwortung wahrzunehmen, Armut zu bekämpfen und Perspektiven zu schaffen. Ich wünsche Dir viel Erfolg und eine glückliche Hand!
net_sentiment author_handle
1 12 katharinadroege.bsky.social
2 11 katharinadroege.bsky.social
3 10 nroettgen.bsky.social
4 10 nroettgen.bsky.social
5 10 katharinadroege.bsky.social
6 10 nouripour.bsky.social
7 9 nroettgen.bsky.social
8 9 nroettgen.bsky.social
9 9 nroettgen.bsky.social
10 9 svenjaschulze.bsky.social
results_rauh %>% # Negativste Posts
arrange(net_sentiment) %>%
select(text, net_sentiment, author_handle) %>%
head(10) text
1 Zwei Jahre ist es her, dass #JinaMahsaAmini vom Mullah-Regime brutal ermordet wurde, weil sie angeblich ihr Kopftuch falsch trug. Auch wenn sich das Regime seitdem mit Terror & Gewalt an der Macht hält, hat es die große Mehrheit der Menschen im Land längst verloren. Sie wollen Freiheit!
2 Der Terroranschlag in Jerusalem ist unfassbar grausam und erschütternd. Ich bin in tiefer Trauer in Gedanken bei den Verletzten und den Angehörigen der Opfer.
3 Ich bin bestürzt, dass der Polizeibeamte in #Mannheim seinen schweren Verletzungen erlegen ist. Mein tiefstes Beileid gilt Familie, Freund*innen und Kolleg*innen. Die furchtbare Tat gegen ihn und alle weiteren Verletzten wird mit der Härte des Rechtsstaates verfolgt werden.
4 Wir erleben gerade in Echtzeit, wie gefährlich unsere Abhängigkeiten von China sind. Firmen, auch im Rüstungsbereich, müssen ihre Produktion drosseln, weil Peking Exportkontrollen für wichtige Rohstoffe eingeführt hat. De-Risking ist zwingend notwendig. \n\nwww.handelsblatt.com/politik/inte...
5 Wir haben nicht den Luxus, dass es nur eine außenpolitische Herausforderung gibt: Auch die geopolitische Rivalität, die von #China ausgeht, beschäftigt uns. Wir werden das strategische De-Risiking von China jetzt endlich angehen. Wirtschaftliche Abhängigkeiten müssen reduziert werden.
6 Jamshid Sharmahd wurde entführt, gefoltert & hingerichtet. Man kann nur tiefste Abscheu vor dem Mullah-Regime empfinden. Bei aller Trauer muss man leider auch sagen, dass die 🇩🇪 Iranpolitik erneut gescheitert ist. Meine Gedanken sind bei Jamshids Familie, die so für sein Leben gekämpft hat.
7 Ich verurteile die Gewalt gegen Studenten und Demonstranten in Bangladesch. Die Versammlungsfreiheit ist ein Grundrecht in einer Demokratie. Die Regierung muss das harte Durchgreifen und die Abschaltung des Internets sofort beenden.
8 Auch unter der Vorgängerregierung herrschte wenig Interesse am Iran. Spätestens nachdem Teheran 2022 ein weiteres EU-Verhandlungsverbot ausschlug und die Revolution im eigenen Land brutal unterdrückte, hätte das Auswärtige Amt seinen Kurs wechseln müssen.
9 Sehr schade und enttäuschend, dass Grüne und FDP gegen den @cducsu.de Antrag zur sofortigen Lieferung von Taurus an die Ukraine gestimmt haben. Wenn sie ihre öffentlichen Aussagen ernst meinen, dann müssen sie jetzt selbst einen Antrag einbringen. Alles andere wäre unglaubwürdig.
10 Allein der Begriff „Lifestyle-Teilzeit“ ist unverschämt. Er erkennt die Lebensrealität vieler nicht an.\n\nAnstatt herablassend über die Menschen im Land zu sprechen, sollte die CDU endlich ihren Job machen. Das heißt auch, für mehr Kinderbetreuung und Pflegeplätze zu sorgen.
net_sentiment author_handle
1 -6 nroettgen.bsky.social
2 -6 katharinadroege.bsky.social
3 -6 katharinadroege.bsky.social
4 -5 nroettgen.bsky.social
5 -5 nroettgen.bsky.social
6 -5 nroettgen.bsky.social
7 -5 nroettgen.bsky.social
8 -5 nroettgen.bsky.social
9 -5 nroettgen.bsky.social
10 -5 katharinadroege.bsky.social
17.2.2 Weitere Optionen für die Sentiment-Analyse in R
Neben quanteda.sentiment gibt es noch einige andere R-Pakete, die für die Sentiment-Analyse verwendet werden können. So bietet z.B. auch das Paket tidytext Möglichkeiten für die Sentiment-Analyse. Eine ausführliche Einführung dazu gibt es im entsprechenden Kapitel des Buchs Text Mining with R: A Tidy Approach.
Einen diktionärbasierten Ansatz für die Sentiment-Analyse verfolgt auch das Paket syuzhet.
Das Paket sentimentr erlaubt die Berechnung der Polarität von Texten in englischer Sprache auf Satzebene. Dabei berücksichtigt es auch sogenannte “Valence Shifters” (d.h. Negationen, Verstärker, Abschwächer).
Komplexere Ansätze für die Sentiment-Analyse bieten z.B. die Pakete sentiment.ai und transforEmotion. Letzteres nutze sogenannte Transformer-Modelle. Beide benötigen allerdings auch eine Python-Installation.
Sentiment-Analysen sind auch mit Large Language Models (LLMs) möglich. Ein interessantes R-Paket für die automatisierte Inhaltsanalyse mit LLMs, das auch für die Sentiment-Analyse eingesetzt werden kann, ist klaus.
17.3 Weitere diktionärbasierte Ansätze
Neben der Sentiment-Analyse können Diktionäre auch genutzt werden, um andere Konstrukte zu messen. Ein Beispiel hierfür ist die Messung von Populismus. Hierfür gibt es das Paket popdictR, welches das auf dem Populismus-Diktionär von Gründl (2020) basiert. Dieses Paket wurde allerdings seit einiger Zeit nicht mehr aktualisiert und ist daher nur mit älteren Versionen von quanteda kompatibel.