library(quanteda)
library(readtext)
library(udpipe)
library(tidyverse)
Benötigte libraries:
quanteda: Korpus erstellen
readtext: Dateien sinnvoll einlesen
udpipe: Korpus annotieren
tidyverse: viele R-Funktionen und ggplot
Zunächst muss der Korpus eingelesen werden:
programs <- readtext("Korpus-Dateien",
docvarsfrom = "filenames",
docvarnames = c("type", "party", "year"),
dvsep = "-",
encoding="utf-8") %>% corpus()
Für die Sentimentanalyse verwenden wir das SentiWS-Wörterbuch. Es wird als data.frame gespeichert, in der ersten Spalte findet sich der Term, in der Zweiten der dazugehörige Sentimentwert. Die Erstellung des Sentiment-Dictionaries wird im Abschnitt “Sentiment” gezeigt.
# Load sentiment dictionary
load("RData/senti_dict.RData")
Außerdem muss der annotierte Korpus geladen werden.
load("RData/annotated_corpus.RData")
head(annotated_model)[c(1:3,5:13)]
## doc_id paragraph_id sentence_id token_id token lemma upos xpos
## 1 doc1 1 1 1 Alternative Alternative NOUN NN
## 2 doc1 1 1 2 für für ADP APPR
## 3 doc1 1 1 3 Deutschland Deutschland PROPN NE
## 4 doc1 1 1 4 Wir wir PROPN NN
## 5 doc1 1 1 5 fordern fordern VERB VVFIN
## 6 doc1 1 1 6 eine ein DET ART
## feats head_token_id
## 1 Case=Nom|Gender=Fem|Number=Sing 5
## 2 <NA> 3
## 3 Case=Acc|Gender=Neut|Number=Sing 1
## 4 Case=Acc|Gender=Neut|Number=Sing 3
## 5 Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin 0
## 6 Case=Acc|Definite=Ind|Gender=Fem|Number=Sing|PronType=Art 8
## dep_rel deps
## 1 nsubj <NA>
## 2 case <NA>
## 3 nmod <NA>
## 4 flat <NA>
## 5 root <NA>
## 6 det <NA>
Die .RData-Datei wurde mit dem folgenden Code erstellt, das Annotieren des gesamten Korpus dauert allerdings seine Zeit.
annotated_model <- udpipe_annotate(udmodel_german, x = programs) %>%
as.data.frame()
save(annotated_model, file='annotated_corpus.RData')
Im nächsten Schritt wird der Korpus aufgeteilt, je nachdem, ob das Wahlprogramm durch eine regierungsbeteiligte Partei erstellt wurde oder durch eine Partei der Opposition.
# partition of corpus
regierung <- c('doc3', 'doc4', 'doc10', 'doc11', 'doc12', 'doc19', 'doc23', 'doc24', 'doc25', 'doc27')
opposition <- c('doc1', 'doc2', 'doc5', 'doc6', 'doc7', 'doc8', 'doc9', 'doc13', 'doc14', 'doc15', 'doc16', 'doc17', 'doc18', 'doc20', 'doc21', 'doc22', 'doc26')
# split into
sub_model_regierung <- subset(annotated_model, doc_id %in% regierung)
sub_model_opposition <- subset(annotated_model, doc_id %in% opposition)
Im folgenden haben wir zwei Listen (das etwas komplizierte R-Äquivalent zu dictionaries in Python), in denen für jedes Dokument die Begriffe gespeichert sind, mit denen die Verfasserin auf sich selbst referieren könnte.
# list of words a party could use to talk about themselves
# first one is name of the party
regierung_list <- list('doc3' = c('bündnis90/die grünen', 'wir'),
'doc4' = c('bündnis90/die grünen', 'wir'),
'doc10' = c('cdu', 'wir'),
'doc11' = c('cdu', 'wir'),
'doc12' = c('cdu', 'wir'),
'doc19' = c('fdp', 'wir'),
'doc23' = c('spd', 'wir'),
'doc24' = c('spd', 'wir'),
'doc25' = c('spd', 'wir'),
'doc27' = c('spd', 'wir'))
opposition_list <- list('doc1' = c('afd', 'alternative', 'wir'),
'doc2' = c('afd', 'alternative', 'wir'),
'doc5' = c('bündnis90/die grünen', 'bündnis90', 'grüne', 'wir'),
'doc6' = c('bündnis90/die grünen', 'bündnis90', 'grüne', 'wir'),
'doc7' = c('bündnis90/die grünen', 'bündnis90', 'grüne', 'wir'),
'doc8' = c('cdu', 'wir'),
'doc9' = c('cdu', 'wir'),
'doc13' = c('die linke', 'linke', 'wir'),
'doc14' = c('die linke', 'linke', 'wir'),
'doc15' = c('die linke', 'linke', 'wir'),
'doc16' = c('fdp', 'wir'),
'doc17' = c('fdp', 'wir'),
'doc18' = c('fdp', 'wir'),
'doc20' = c('fdp', 'wir'),
'doc21' = c('pds', 'wir'),
'doc22' = c('linkspartei.pds', 'wir'),
'doc26' = c('spd', 'wir'))
Hiermit sollen jene Verben gesammelt werden, mit denen Parteien Aussagen über sich selbst treffen. Dazu helfen uns die folgenden beiden Funktionen:
# function to extract info from "feats"-column to separate column
featsinfo_to_column <- function(data, name) {
data <- cbind(data, c('-'))
names(data)[length(names(data))] <- tolower(name)
# separate data
data_part1 <- data[grepl(name, data$feats) == TRUE,]
data_part2 <- data[grepl(name, data$feats) == FALSE,]
# extract data
pattern <- paste0(".*(", name, "=)([A-Za-z]+)[|]?.*")
data_part1[,ncol(data)] <- sub(pattern, "\\2",
data_part1$feats)
modified_data <- rbind(data_part1, data_part2)
return(modified_data)
}
featsinfo_to_column(annotated_data, translation_list, senti_data):
annotated_data ist ein mit udpipe annotierter (Teil-)Korpus
name ist der (großgeschriebene) Name des Features, welches aus der Spalte feats extrahiert werden soll.
Diese fügt eine neue Spalte an das Dataframe an, in welche die Information zum Feature gespeichert wird.
roots_for_group <- function(annotated_data, translation_list, senti_data) {
# extract roots
roots <- annotated_data %>%
subset(sentence %in% subset(., dep_rel == 'nsubj' & tolower(token) %in% unlist(translation_list[doc_id]))$sentence) %>%
subset(dep_rel == 'root')
# extract relevant information from "feats" column
roots <- roots[c(1, 6:7, 10)] %>%
featsinfo_to_column('Tense') %>%
featsinfo_to_column('Mood') %>%
featsinfo_to_column('VerbForm')
roots <- roots[-c(2,4)] # cut out feats and token
roots$senti_ws <- '-' # add sentiment column
for (w in unique(roots$lemma)) {
if (w %in% senti_data$term) {
if (length(senti_data[senti_data$term == w,]$value) < 2) {
roots[roots$lemma == w,]$senti_ws <- senti_data[senti_data$term == w,]$value
}
}
}
# count words
roots <- roots[2:6]
roots <- aggregate(cbind(roots[0],numdup=1), roots, length)
roots <- roots[order(roots$numdup, decreasing = TRUE),] %>%
filter(numdup > 2)
names(roots)[names(roots) == 'numdup'] <- 'freq'
return(roots)
}
roots_for_group(annotated_data, translation_list, senti_data):
annotated_data ist ein mit udpipe annotierter (Teil-)Korpus
translation_list ist eine Liste nach dem Stil der Listen regierung_list und opposition_list, in der für jedes Dokument mögliche Subjekte gesammelt sind, zu welchen Verben gesammelt werden sollen (s.o.).
senti_data ist ein data.frame wie oben beschrieben, mit einer Spalte term und einer Salte value
Diese Funktion sammelt die Lemmata der Verben, mit denen Parteien ihr eigenes Handeln beschreiben und speichert allerlei Informationen über sie. Gesammelt werden tense, mood, verbform, Semtimentwert sowie Häufigkeit.
translation_complete <- c(regierung_list, opposition_list)
head(roots_for_group(annotated_model, translation_complete, senti_dict))
## lemma tense mood verbform senti_ws freq
## 1 wollen Pres Ind Fin - 1229
## 2 setzen Pres Ind Fin - 1163
## 3 brauchen Pres Ind Fin - 621
## 4 stärken - - Inf 0.004 557
## 5 fordern Pres Ind Fin - 534
## 6 lehnen Pres Ind Fin - 385
Die folgende Funktion sammelt Sentimentwerte und Frequenz für beliebige Werte einer Kategorie.
collect_sentiment_for_cat(annotated_data, category, value, senti_data):
annotated_data ist ein mit udpipe annotierter (Teil-)Korpus
category ist die Spalte, in der gesucht werden soll.
value der Wert, nach dem gefiltert werden soll.
# function to collect sentiment for category
collect_sentiment_for_cat <- function(annotated_data, category, value, senti_data) {
# filter data
index <- grep(category, colnames(annotated_data))
filtered_data <- subset(annotated_data, annotated_data[,index] == value)
filtered_data$senti_ws <- '-'
senti_df <- filtered_data[c(7,8)]
senti_df$senti_ws <- '-' # add sentiment column
for (w in unique(senti_df$lemma)) {
if (w %in% senti_data$term) {
if (length(senti_data[senti_data$term == w,]$value) < 2) {
senti_df[senti_df$lemma == w,]$senti_ws <- senti_data[senti_data$term == w,]$value
}
}
}
# count words
senti_df <- aggregate(cbind(senti_df[0],numdup=1), senti_df, length)
senti_df <- senti_df[order(senti_df$numdup, decreasing = TRUE),] %>%
filter(numdup > 1)
names(senti_df)[names(senti_df) == 'numdup'] <- 'freq'
return(senti_df[-2])
}
Das Ergebnis sieht wiefolgt aus:
opp_nouns <- collect_sentiment_for_cat(sub_model_opposition, "upos", 'NOUN', senti_dict)
head(opp_nouns)
## lemma senti_ws freq
## 1 Mensch - 2028
## 2 Land - 1165
## 3 Kind - 966
## 4 Unternehmen - 800
## 5 Jahr - 794
## 6 Gesellschaft - 788
gov_nouns <- collect_sentiment_for_cat(sub_model_regierung, "upos", 'NOUN', senti_dict)
head(gov_nouns)
## lemma senti_ws freq
## 1 Mensch - 1064
## 2 Land - 967
## 3 Kind - 547
## 4 Jahr - 449
## 5 Gesellschaft - 431
## 6 Zukunft - 416
opp_adv <- collect_sentiment_for_cat(sub_model_opposition, "upos", 'ADJ', senti_dict)
head(opp_adv)
## lemma senti_ws freq
## 1 gut 0.3716 1738
## 2 sozial - 1485
## 3 neu 0.004 1448
## 4 öffentlich - 1127
## 5 stark 0.004 725
## 6 europäisch - 710
gov_adv <- collect_sentiment_for_cat(sub_model_regierung, "upos", 'ADJ', senti_dict)
head(gov_adv)
## lemma senti_ws freq
## 1 gut 0.3716 989
## 2 neu 0.004 957
## 3 sozial - 562
## 4 stark 0.004 540
## 5 wichtig 0.3822 496
## 6 international - 461
Mithilfe der durch roots_for_group-Funktion lassen sich jene Prädikate sammeln, welche die Parteien verwenden, wenn sie in ihren Programmen Aussagen über sich selbst tätigen, also in Sätzen wie “Wir forden…” oder “Die FDP befürwortet…”. Zunächst haben wir überprüft, wie sich die quantitative Verteilung der Verwendung dieser Prädikate für Regierungs- und Oppositionsparteien gestaltet.
Der erste Schritt ist die Erstellung der root-Dataframes für die Subsets des annotierten Modells.
opp_roots <- roots_for_group(sub_model_opposition, opposition_list, senti_dict)
head(opp_roots)
## lemma tense mood verbform senti_ws freq
## 1 wollen Pres Ind Fin - 753
## 2 setzen Pres Ind Fin - 712
## 3 fordern Pres Ind Fin - 481
## 4 brauchen Pres Ind Fin - 403
## 5 stärken - - Inf 0.004 301
## 6 lehnen Pres Ind Fin - 245
gov_roots <- roots_for_group(sub_model_regierung, regierung_list, senti_dict)
head(gov_roots)
## lemma tense mood verbform senti_ws freq
## 1 wollen Pres Ind Fin - 476
## 2 setzen Pres Ind Fin - 450
## 3 stärken - - Inf 0.004 256
## 4 brauchen Pres Ind Fin - 217
## 5 stehen Pres Ind Fin - 145
## 6 treten Past Ind Fin - 143
Zunächst betrachten wir also die Frequenz. Nach der Erstellung eines Dataframes, welches die Top50-Prädikate der Oppositionswahlprogramme mit den Top50-Prädikaten der Regierungswahlprogramme vereinigt, sowie der Normalisierung der Werte kann man die Verteilung plotten.
# Self referential verbs
verbs.top.50 <- union(head(gov_roots, 50)$lemma, head(opp_roots, 50)$lemma)
freq.verbs <- data.frame(matrix(ncol=3, nrow=0))
colnames(freq.verbs) <- c("lemma", "freq_gov", "freq_opp")
sum.all.gov <- sum(gov_roots$freq)
sum.all.opp <- sum(opp_roots$freq)
for (i in 1:length(verbs.top.50)){
curr.verb <- verbs.top.50[i]
freq.gov <- sum(filter(gov_roots, lemma == curr.verb)$freq)/sum.all.gov
freq.opp <- sum(filter(opp_roots, lemma == curr.verb)$freq)/sum.all.opp
curr.row <- data.frame(lemma=curr.verb, freq_gov=freq.gov, freq_opp = freq.opp)
freq.verbs <- rbind(freq.verbs, curr.row)
}
freq.verbs
## lemma freq_gov freq_opp
## 1 wollen 0.0750586396 0.0886846767
## 2 setzen 0.0777169664 0.0849202834
## 3 stärken 0.0425332291 0.0333259522
## 4 brauchen 0.0339327600 0.0446191320
## 5 stehen 0.0226739640 0.0230292294
## 6 treten 0.0231430805 0.0224756422
## 7 lehnen 0.0232994527 0.0286758193
## 8 unterstützen 0.0362783425 0.0255757307
## 9 verbessern 0.0240813135 0.0121789194
## 10 fördern 0.0267396403 0.0201505757
## 11 haben 0.0157935887 0.0056465899
## 12 schaffen 0.0309616888 0.0302258636
## 13 ausbauen 0.0139171228 0.0087466785
## 14 halten 0.0136043784 0.0108503100
## 15 fortsetzen 0.0114151681 0.0008857396
## 16 einsetzen 0.0123534011 0.0099645704
## 17 weiterentwickeln 0.0112587959 0.0053144376
## 18 sorgen 0.0170445661 0.0118467671
## 19 machen 0.0172009382 0.0197077059
## 20 einführen 0.0093823299 0.0116253322
## 21 fordern 0.0093823299 0.0577945084
## 22 bekennen 0.0082877248 0.0032108060
## 23 streben 0.0081313526 0.0074180691
## 24 nutzen 0.0089132134 0.0047608503
## 25 stellen 0.0104769351 0.0107395926
## 26 erreichen 0.0120406568 0.0089681134
## 27 sehen 0.0062548866 0.0104074402
## 28 erhöhen 0.0092259578 0.0060894597
## 29 vorantreiben 0.0059421423 0.0033215235
## 30 ermöglichen 0.0071931196 0.0083038087
## 31 sicherstellen 0.0057857701 0.0044286980
## 32 werden 0.0051602815 0.0037643933
## 33 entwickeln 0.0059421423 0.0034322409
## 34 gestalten 0.0057857701 0.0062001771
## 35 sichern 0.0060985145 0.0040965456
## 36 umsetzen 0.0050039093 0.0023250664
## 37 erleichtern 0.0045347928 0.0038751107
## 38 geben 0.0076622361 0.0068644818
## 39 prüfen 0.0056293980 0.0036536758
## 40 wissen 0.0062548866 0.0055358725
## 41 überprüfen 0.0040656763 0.0009964570
## 42 erhalten 0.0068803753 0.0044286980
## 43 abschaffen 0.0034401876 0.0093002657
## 44 kämpfen 0.0034401876 0.0091895483
## 45 beenden 0.0006254887 0.0081930912
## 46 nehmen 0.0032838155 0.0059787422
## 47 streiten 0.0007818608 0.0059787422
## 48 ändern 0.0015637217 0.0067537644
## 49 wenden 0.0015637217 0.0056465899
## 50 verhindern 0.0032838155 0.0048715678
## 51 schützen 0.0045347928 0.0052037201
## 52 bekämpfen 0.0039093041 0.0043179805
gov.greater <- ifelse(freq.verbs$freq_gov >= freq.verbs$freq_opp, TRUE, FALSE)
freq.verbs$gov.greater <- gov.greater
# Plot results
ggplot(freq.verbs, aes(y = freq_gov, x = freq_opp, label =lemma, color = gov.greater))+
geom_text(size = 5)+
scale_x_continuous(trans = 'log10', breaks = c(0, 0.001, 0.010, 0.1)) +
scale_y_continuous(trans = 'log10', breaks = c(0, 0.001, 0.010, 0.05))+
scale_color_manual(values = c('TRUE' = 'darkblue', 'FALSE' = 'darkred'), guide = "none")+
theme_minimal()+
labs(x="Relative Frequenz in Oppositionsparteien",
y="Relative Frequenz in Regierungsparteien",
title="Verben in selbstreferentiellen Sätzen")+
theme(axis.text=element_text(size=16),
axis.title=element_text(size=20))
Auch die Zeitformen der Verben werden durch die Funktion roots_for_groops festgehalten und können so gegenübergestellt werden:
## TENSE
s.gov <- sum(gov_roots$freq)
s.opp <- sum(opp_roots$freq)
gov.type <- c("opposition", "goverment")
pres.type <- c(sum(filter(opp_roots, tense == "Pres")$freq)/s.opp,
sum(filter(gov_roots, tense == "Pres")$freq)/s.gov)
past.type <- c(sum(filter(opp_roots, tense == "Past")$freq)/s.opp,
sum(filter(gov_roots, tense == "Past")$freq)/s.gov)
tense <- data.frame(type=gov.type, pres =pres.type, past=past.type)
tense
## type pres past
## 1 opposition 0.5357617 0.02325066
## 2 goverment 0.4204848 0.03424550
Gleiches ist möglich für die Kategorie “VerbForm”:
## VERBFORM
inf.type <- c(sum(filter(opp_roots, verbform == "Inf")$freq)/s.opp,
sum(filter(gov_roots, verbform == "Inf")$freq)/s.gov)
fin.type <- c(sum(filter(opp_roots, verbform == "Fin")$freq)/s.opp,
sum(filter(gov_roots, verbform == "Fin")$freq)/s.gov)
part.type <- c(sum(filter(opp_roots, verbform == "Part")$freq)/s.opp,
sum(filter(gov_roots, verbform == "Part")$freq)/s.gov)
verbform <- data.frame(type=gov.type, inf=inf.type, fin =fin.type, part = part.type)
verbform
## type inf fin part
## 1 opposition 0.3799823 0.5590124 0.01494686
## 2 goverment 0.4448788 0.4547303 0.06176701
Mit der Funktion sentiment_for_cat lassen sich Sentimentwerte und Frequenzen für Tokens einer bestimmten Kategorie sammeln. Im folgenden wurden zunächst die Werte für Substantive und Adjektive gesammelt.
opp_nouns <- collect_sentiment_for_cat(sub_model_opposition, "upos", 'NOUN', senti_dict)
gov_nouns <- collect_sentiment_for_cat(sub_model_regierung, "upos", 'NOUN', senti_dict)
opp_adv <- collect_sentiment_for_cat(sub_model_opposition, "upos", 'ADJ', senti_dict)
gov_adv <- collect_sentiment_for_cat(sub_model_regierung, "upos", 'ADJ', senti_dict)
head(opp_nouns)
## lemma senti_ws freq
## 1 Mensch - 2028
## 2 Land - 1165
## 3 Kind - 966
## 4 Unternehmen - 800
## 5 Jahr - 794
## 6 Gesellschaft - 788
head(gov_nouns)
## lemma senti_ws freq
## 1 Mensch - 1064
## 2 Land - 967
## 3 Kind - 547
## 4 Jahr - 449
## 5 Gesellschaft - 431
## 6 Zukunft - 416
Als nächstes folgt die Normalisierung der Frequenzwerte:
## top nouns opposition und Government
noun.top <- union(head(opp_nouns, 60)$lemma, head(gov_nouns, 40)$lemma)
sum.gov <- sum(gov_nouns$freq)
sum.opp <- sum(opp_nouns$freq)
freq.nouns <- data.frame(matrix(ncol=3, nrow=0))
colnames(freq.nouns) <- c("lemma", "freq_gov", "freq_opp")
for (i in 1:length(noun.top)){
curr.noun <- noun.top[i]
gov.freq <- sum(filter(gov_nouns, lemma == curr.noun)$freq)/sum.gov
opp.freq <- sum(filter(opp_nouns, lemma == curr.noun)$freq)/sum.opp
tmp.data <- data.frame(lemma=curr.noun, gov_freq = gov.freq, opp_freq = opp.freq)
freq.nouns <- rbind(freq.nouns, tmp.data)
}
freq.nouns$gov.greater <- ifelse(freq.nouns$gov_freq >= freq.nouns$opp_freq, TRUE, FALSE)
Und schließlich der resultierende Plot:
ggplot(freq.nouns, aes(y = gov_freq, x = opp_freq, label =lemma, color = gov.greater))+
geom_text(size = 5)+
scale_x_continuous(trans = 'log10', breaks = c(0, 0.001, 0.010, 0.1)) +
scale_y_continuous(trans = 'log10', breaks = c(0, 0.001, 0.010, 0.05)) +
scale_color_manual(values = c('TRUE' = 'darkblue', 'FALSE' = 'darkred'), guide = "none")+
theme_minimal() +
labs(x="Relative Frequenz in Oppositionsparteien",
y="Relative Frequenz in Regierungsparteien",
title="Häufige Nomen bei Oppositions- und Regierungsparteien")+
theme(axis.text=element_text(size=16),
axis.title=element_text(size=20))
Diese Prozedur funktioniert analog für Adjektive:
## OPP GOV ADJ
head(opp_adv)
## lemma senti_ws freq
## 1 gut 0.3716 1738
## 2 sozial - 1485
## 3 neu 0.004 1448
## 4 öffentlich - 1127
## 5 stark 0.004 725
## 6 europäisch - 710
head(gov_adv)
## lemma senti_ws freq
## 1 gut 0.3716 989
## 2 neu 0.004 957
## 3 sozial - 562
## 4 stark 0.004 540
## 5 wichtig 0.3822 496
## 6 international - 461
adj.top <- union(head(opp_adv, 50)$lemma, head(gov_adv, 50)$lemma)
sum.gov <- sum(gov_adv$freq)
sum.opp <- sum(opp_adv$freq)
freq.adj <- data.frame(matrix(ncol=3, nrow=0))
colnames(freq.nouns) <- c("lemma", "freq_gov", "freq_opp")
for (i in 1:length(adj.top)){
curr.adj <- adj.top[i]
gov.freq <- sum(filter(gov_adv, lemma == curr.adj)$freq)/sum.gov
opp.freq <- sum(filter(opp_adv, lemma == curr.adj)$freq)/sum.opp
tmp.data <- data.frame(lemma=curr.adj, gov_freq = gov.freq, opp_freq = opp.freq)
freq.adj <- rbind(freq.adj, tmp.data)
}
freq.adj$gov.greater <- ifelse(freq.adj$gov_freq >= freq.adj$opp_freq, TRUE, FALSE)
ggplot(freq.adj, aes(y = gov_freq, x = opp_freq, label =lemma, color = gov.greater)) +
geom_text(size = 5) +
scale_x_continuous(trans = 'log10', breaks = c(0, 0.005, 0.010, 0.020)) +
scale_y_continuous(trans = 'log10', breaks = c(0, 0.020, 0.010, 0.005)) +
scale_color_manual(values = c('TRUE' = 'darkblue', 'FALSE' = 'darkred'), guide = "none")+
theme_minimal() +
ggtitle("Häufige Adjektive bei Oppositions- und Regierungsparteien") +
labs(x="Relative Frequenz in Oppositionsparteien",
y="Relative Frequenz in Regierungsparteien") +
theme(axis.text=element_text(size=16),
axis.title=element_text(size=20))
Auch die Sentimentwerte für einzelne Kategorien lassen sich so analysieren. Nach der Aufsummierung der Addjektive lässt sich ein Dataframe erstellen:
# Government
adj.s.gov <- sum(gov_adv$freq)
tmp.sent <- ifelse(gov_adv$senti_ws == "-", 0, gov_adv$senti_ws)
gov_adv$tmp.sent <- as.numeric(tmp.sent)
neg.adj <- filter(gov_adv, tmp.sent<0)
f <- abs(sum(neg.adj$tmp.sent * neg.adj$freq/adj.s.gov))
pos.adj <- filter(gov_adv, tmp.sent>0)
g <- sum(pos.adj$tmp.sent * pos.adj$freq/adj.s.gov)
# Opposition
adj.s.opp <- sum(opp_adv$freq)
tmp.sent <- ifelse(opp_adv$senti_ws == "-", 0, opp_adv$senti_ws)
opp_adv$tmp.sent <- as.numeric(tmp.sent)
neg.adj <- filter(opp_adv, tmp.sent<0)
h <- abs(sum(neg.adj$tmp.sent * neg.adj$freq/adj.s.opp))
pos.adj <- filter(opp_adv, tmp.sent>0)
i <- sum(pos.adj$tmp.sent * pos.adj$freq/adj.s.opp )
adv_senti <- c('positive', 'negative', 'positive', 'negative')
combi_assignment <- c('Regierung', 'Regierung', 'Opposition', 'Opposition')
adv_senti_df <- data.frame(adv_senti, combi_assignment)
adv_senti_df$Wert <- c(g, f, i, h)
adv_senti_df
## adv_senti combi_assignment Wert
## 1 positive Regierung 0.04287049
## 2 negative Regierung 0.01093616
## 3 positive Opposition 0.03192539
## 4 negative Opposition 0.01637040
Der Plot sieht wiefolgt aus:
adv_senti_plot <- ggplot(adv_senti_df, aes(x=adv_senti, y=Wert, fill=combi_assignment)) +
geom_bar(stat='identity', position='dodge') +
xlab('Sentiment') +
ylab('kumulierter Wert') +
ggtitle('kumulierte Sentimentwerte für Adjektive') +
guides(fill=guide_legend(title="Position")) +
scale_fill_manual("Position", values = c("Opposition" = "darkred", "Regierung" = "darkblue"))
adv_senti_plot