Blogbeitrag von Valentin Kathriner

Dieses Dokument beschreibt die Verarbeitung und Analyse der Daten, welche als Grundlage für den Artikel “Corona und Medienkonsum: Wo sich Massnahmenkritiker ihre Meinung bilden”, im Rahmen der Vorbereitung für das Forschungsseminar Datenjournalismus an der UZH entstanden sind. Die Analysen wurden in R-Studio und RMarkdown durchgeführt.

Daten vorbereiten

Als erstes werden alle nötigen Pakete geladen und installiert. Anschliessend wird das Arbeitsverzeichnis definiert und der Datensatz geladen.

# Benötigte Pakete installieren und laden

library(dplyr)
library(tidyr)
library(reshape2)
library(ggplot2)
library(ggridges)
library(ggalt)
library(forcats)
library(tidyverse)
library(data.table)
library(tidyverse)
library(ggalt)

# Arbeitsverzeichnis definieren
setwd(paste0("/Users/Valentin/Dropbox/Dropbox/Studium/Master Komm & Pol/HS 2020/DDJ/Arbeit"))

# Dateipfad definieren
file_path <- "/Users/Valentin/Dropbox/Dropbox/Studium/Master Komm & Pol/HS 2020/DDJ/Arbeit/Daten/Final/Daten_DDJ_HS20_Olat/Corona-Monitor/2-Daten/CoronaMonitorAll.csv"

# Datensatz laden
corona <- read.csv(file_path,
                  sep = ",",
                  encoding = "UTF-8",
                  stringsAsFactors = FALSE)

# Welle -> Welle
table(corona$Welle)

# Umfrage -> Umfragen
table(corona$Umfrage, corona$Welle)

# token -> Personen
head(corona$token)

Als nächstes wird der Arbeitsdatensatz erstellt mit allen benötigten Variablen.

# Arbeitsdatensatz erstellen mit allen benötigten Variablen
corona_v <- corona %>% select(Welle, X, id, age, sex, edu, kanton, party, massnLockdown, weight,
                              massnBewegung, kommunikation, medien_SQ001, 
                              medien_SQ002, medien_SQ003, medien_SQ004, 
                              medien_SQ005, kanalY_SQ001, kanalY_SQ002, 
                              kanalY_SQ003, kanalY_SQ004, kanalY_SQ005, 
                              kanalY_SQ006, kanalY_other, 
                              kanalN_SQ001, kanalN_SQ002,
                              kanalN_SQ003, kanalN_SQ004, kanalN_SQ005, kanalN_SQ006)

Recodieren von Variablen

Um die nötigen Berechnungen vorzunehmen, müssen einige Variablen recodiert werden. Als erstes wird die Variable “massnBewegung” recodiert und zu einer Dummy-Variable gemacht.

corona_v <- corona_v %>% mutate(
  massnBewegung_ja = case_when(
    massnBewegung %in% c("Sind angemessen", "Gehen eher zu wenig weit", "Gehen viel zu wenig weit") ~ "Befürworter",
    massnBewegung %in% c("Gehen eher zu weit", "Gehen viel zu weit") ~ "Gegner"))

Als nächstes werden aus den einzelnen Kanal-Variablen ebenfalls jeweils Dummy-Variablen erstellt.

corona_v <- corona_v %>% mutate(
  socialmedia = case_when(
    kanalY_SQ004 %in% c("Soziale Medien: Selected") ~ 1,
    kanalY_SQ004 %in% c("Soziale Medien: Not selected") ~ 0),
  
  web = case_when(
    kanalY_SQ001 %in% c("Webseiten von staatlichen Organisationen (BAG usw.): Selected") ~ 1,
    kanalY_SQ001 %in% c("Webseiten von staatlichen Organisationen (BAG usw.): Not selected") ~ 0),
  
  app = case_when(
    kanalY_SQ002 %in% c("Offizielle Warn- und Informations-Apps (Alertswiss usw.): Selected") ~ 1,
    kanalY_SQ002 %in% c("Offizielle Warn- und Informations-Apps (Alertswiss usw.): Not selected") ~ 0),
  
  kl_medien = case_when(
    kanalY_SQ003 %in% c("Klassische Medien: Selected") ~ 1,
    kanalY_SQ003 %in% c("Klassische Medien: Not selected") ~ 0),
  
  hausarzt = case_when(
    kanalY_SQ005 %in% c("Hausarzt/Hausärztin: Selected") ~ 1,
    kanalY_SQ005 %in% c("Hausarzt/Hausärztin: Not selected") ~ 0),
  
  umfeld = case_when(
    kanalY_SQ006 %in% c("Persönliches Umfeld: Selected") ~ 1,
    kanalY_SQ006 %in% c("Persönliches Umfeld: Not selected") ~ 0)
  
  )

Hier werden die Variablen zur Einschätzung der Medienberichterstattung recodiert.

corona_v <- corona_v %>% mutate(
  info = case_when(
    medien_SQ001 %in% c("Sie informieren umfassend: Not selected") ~ 0,
    medien_SQ001 %in% c("Sie informieren umfassend: Selected") ~ 1),
  
  sachlich = case_when(
    medien_SQ002 %in% c("Sie ordnen sachlich ein: Not selected") ~ 0,
    medien_SQ002 %in% c("Sie ordnen sachlich ein: Selected") ~ 1),
  
  panik = case_when(
    medien_SQ003 %in% c("Sie tragen zu Panik bei: Not selected") ~ 0,
    medien_SQ003 %in% c("Sie tragen zu Panik bei: Selected") ~ 1),
  
  ausmass = case_when(
    medien_SQ004 %in% c("Sie unterschätzen das Ausmass der Krise: Selected") ~ 1,
    medien_SQ004 %in% c("Sie unterschätzen das Ausmass der Krise: Not selected") ~ 0),
  
  dauerbericht = case_when(
    medien_SQ005 %in% c("Sie übertreiben mit ihrer Dauerberichterstattung: Not selected") ~ 0,
    medien_SQ005 %in% c("Sie übertreiben mit ihrer Dauerberichterstattung: Selected") ~ 1)
  
)

Zum Schluss werden die einzelnen Wellen noch in Monaten umcodiert.

corona_v <- corona_v %>% mutate(
  Welle=recode(Welle, 
                   `1`="März",
                   `2`="April",
               `3`="Mai",
               `4`="Juni",
               `5`="Okt.")
)

Datenauswertung und Plots erstellen

Als nächstes wird die Datenauswertung vorgenommen und die einzelnen Plots erstellt.

Einschätzung Behördenkommunikation

Als erstes wird der gewichtete Durchschnittswert der Einschätzung der Behördenkommunikation pro Welle ermittelt (Unterteilt nach Massnehmenbefürworter und -gegner).

channel_df8 <- corona_v %>% 
  mutate(kommunikation_num = as.numeric(stringr::str_extract(kommunikation, "[0-9]+"))) %>%
  group_by(Welle, massnBewegung_ja) %>%
  select(kommunikation_num) %>%
  mutate(kommunikation_num = weighted.mean(kommunikation_num, na.rm=T, weight = weight)) %>%
  distinct()

Anschliessend wird der dazugehörige Line-Plot erstellt.

channel_df8 %>%
  na.omit() %>%
  ggplot() +
  aes(x = Welle, y = kommunikation_num, colour = massnBewegung_ja, group = massnBewegung_ja, fill = massnBewegung_ja) + geom_line(size= 1.5) +
  geom_point(size=7.5) +
  theme_bw(base_family="Helvetica") +
  ylim(1, 5) +
  xlim(c("März", "April", "Mai", "Juni", "Okt.")) +
  scale_color_manual(values = c("#06D6A0", "#EF476F")) +
  theme(panel.grid.major=element_blank()) +
  labs(x=NULL, y="Einschätzung Kommunikation Ø",
       caption="Daten: Forschungsstelle sotomo (Corona-Monitor, Welle 1-5, 2020)") +
  theme(plot.title=element_text(face="bold", size = 14, hjust = 0))+ 
  theme(plot.subtitle=element_text(face="italic", size=12, margin=margin(b=12)))+ 
  theme(plot.caption=element_text(size=9, margin=margin(t=12), color="#7a7d7e")) +
  geom_text(color="#ffffff", size=2.75, vjust= 0.4,
            aes(x=Welle, y=kommunikation_num, label= round(kommunikation_num, digits = 1))) +
  theme(
    panel.border = element_blank()
  ) +
  theme(legend.title = element_blank()) +
  theme(legend.position="bottom")

Einschätzung Behördenkommunikation

Als nächstes werden die gewichteten Durchschnittswerte für die Einschätzung der Medienberichterstattung berechnet.

channel_df11 <- corona_v %>% 
  group_by(Welle, massnBewegung_ja) %>%
  select(info, sachlich, panik, ausmass, dauerbericht) %>%
  mutate(info = weighted.mean(info, na.rm=T, weight = weight)) %>%
  mutate(sachlich = weighted.mean(sachlich, na.rm=T, weight = weight)) %>%
  mutate(panik = weighted.mean(panik, na.rm=T, weight = weight)) %>%
  mutate(ausmass = weighted.mean(ausmass, na.rm=T, weight = weight)) %>%
  mutate(dauerbericht = weighted.mean(dauerbericht, na.rm=T, weight = weight)) %>%
  distinct()

Danach wird der dazugehörige Line-Plot erstellt.

# Beschriftung für Items erstellen
medien.labs <- c("Sie\nunterschätzen\ndas Ausmass\nder Krise", "Sie tragen zu\nPanik bei", "Sie\ninformieren\numfassend", "Sie ordnen\nsachlich ein", "Sie\nübertreiben\nmit ihrer\nDauerberichterstattung")
names(medien.labs) <- c("ausmass", "panik", "info", "sachlich", "dauerbericht")

#Line-Plot
channel_df11 %>%
  gather("Type", "value", -Welle, -massnBewegung_ja) %>%
  na.omit() %>%
  ggplot(aes(x = Welle, y = value*100, group = massnBewegung_ja, color = massnBewegung_ja)) +
  scale_x_discrete() +
  scale_y_continuous() +
  geom_line(size= 1.5) +
  geom_point(size=6) +
  theme_bw(base_family="Helvetica") +
  ylim(0, 100) +
  xlim(c("März", "April", "Mai", "Juni", "Okt.")) +
  facet_wrap(~Type, ncol = 5,scales = "free_x", labeller = labeller(Type = medien.labs)) +
  theme(
    strip.background = element_blank(),
    panel.border = element_blank()
  ) +
  scale_color_manual(values = c("#06D6A0", "#EF476F")) +
  labs(x=NULL, y="Einschätzung Medienberichterstattung Ø (Zustimmung in %)",
       caption="Daten: Forschungsstelle sotomo (Corona-Monitor, Welle 1-5, 2020)") +
  theme(plot.title=element_text(face="bold", size = 18, hjust = 0))+ 
  theme(plot.subtitle=element_text(face="italic", size=12, margin=margin(b=12)))+ 
  theme(plot.caption=element_text(size=9, margin=margin(t=12), color="#7a7d7e")) +
  geom_text(color="#ffffff", size=2.75, vjust= 0.4,
            aes(x=Welle, y=value*100, label= round(value*100))) +
  theme(legend.title = element_blank()) +
  theme(legend.position="bottom")

Entwicklung Medienkonsum nach Welle

Als nächstes wird der Medienkonsum pro Welle berechnet (Unterteilt nach Befürwortern und Gegnern)

channel_df9 <- corona_v %>% 
  group_by(Welle, massnBewegung_ja) %>%
  select(socialmedia, web, app, kl_medien, hausarzt, umfeld) %>%
  mutate(socialmedia = weighted.mean(socialmedia, na.rm=T, weight = weight)) %>%
  mutate(web = weighted.mean(web, na.rm=T, weight = weight)) %>%
  mutate(app = weighted.mean(app, na.rm=T, weight = weight)) %>%
  mutate(kl_medien = weighted.mean(kl_medien, na.rm=T, weight = weight)) %>%
  mutate(hausarzt = weighted.mean(hausarzt, na.rm=T, weight = weight)) %>%
  mutate(umfeld = weighted.mean(umfeld, na.rm=T, weight = weight)) %>%
  distinct()

Und der dazugehörige Plot erstellt.

channel_df9 %>%
  gather("Type", "value", -Welle, -massnBewegung_ja) %>%
  na.omit() %>%
  ggplot(aes(x = Welle, y = value*100, colour = Type, group = Type)) +
  scale_x_discrete() +
  scale_y_continuous() +
  geom_line(size= 1.5) +
  geom_point(size=7) +
  theme_bw(base_family="Helvetica") +
  ylim(0, 100) +
  xlim(c("April", "Mai", "Juni")) +
  facet_wrap(~massnBewegung_ja,scales = "free_x") +
  theme(
    strip.background = element_blank(),
    panel.border = element_blank()
  ) +
  scale_color_manual(values = c("#9297C4","#F1BF98", "#1B9AAA", "#FFC43D", "#F58066", "#4FC8F8"), labels = c("Offizielle Warn- und\nInformations-Apps\n(Alertswiss usw.)", "Hausarzt/ Hausärztin",  "Klassische Medien", "Soziale Medien", "Persönliches Umfeld", "Webseiten von\nstaatlichen\nOrganisationen\n(BAG usw.)")) +
  labs(x=NULL, y="Anteil (%)",
       caption="Daten: Forschungsstelle sotomo (Corona-Monitor, Welle 1-5, 2020)") +
  theme(plot.title=element_text(face="bold", size = 18))+ 
  theme(plot.subtitle=element_text(face="italic", size=12, margin=margin(b=12)))+ 
  theme(plot.caption=element_text(size=9, margin=margin(t=12), color="#7a7d7e")) +
  geom_text(color="#ffffff", size=2.75, vjust= 0.4,
            aes(x=Welle, y=value*100, label= round(value*100))) +
  theme(
    strip.background = element_blank(),
    panel.border = element_blank()
  ) +
  theme(legend.title = element_blank()) +
  theme(legend.position="bottom")

ggsave(filename = "Medienkonsum Entwicklung", device='png', dpi=300)

Unterschiede Medienkonsum in Welle 4 (Juni)

Als nächstes werden die Unterschiede zwischen den Befürwortern und Gegner in Welle 4 berechnet.

channel_df2 <- corona_v %>% 
  group_by(Welle, massnBewegung_ja) %>%
  select(socialmedia, web, app, kl_medien, hausarzt, umfeld) %>%
  mutate(socialmedia = weighted.mean(socialmedia, na.rm=T, weight = weight)) %>%
  mutate(web = weighted.mean(web, na.rm=T, weight = weight)) %>%
  mutate(app = weighted.mean(app, na.rm=T, weight = weight)) %>%
  mutate(kl_medien = weighted.mean(kl_medien, na.rm=T, weight = weight)) %>%
  mutate(hausarzt = weighted.mean(hausarzt, na.rm=T, weight = weight)) %>%
  mutate(umfeld = weighted.mean(umfeld, na.rm=T, weight = weight)) %>%
  distinct()
gap <- channel_df2 %>%
  filter(Welle == "Juni") %>%
  gather("Type", "value",-massnBewegung_ja, -Welle) %>%
  spread(key = massnBewegung_ja, value = value) %>%
  mutate(gap_b_g = Gegner - Befürworter)

Hier wird eine Funktion erstellt, damit die Prozentzeichen im Plot abgebildet werden.

percent_first <- function(x) {
  x <- sprintf("%d%%", round(x*100))
}

Hier wird der Dumbbell-Plot erstellt.

gap %>% 
  ggplot() +
  geom_segment(data=gap, aes(y=Type, yend=Type , x=0, xend=100), color="#b2b2b2", size=0.1) +
  geom_dumbbell(data=gap, aes(y=Type, x=Befürworter*100, xend=Gegner*100),
              size=1, color="#b2b2b2", size_x=5.5, size_xend = 5.5, colour_x = "#06D6A0", colour_xend = "#EF476F") +
  geom_text(data=filter(gap, Type=="web"),
                       aes(x=Gegner*100, y=Type, label="Gegner"),
                       color="#EF476F", size=3.5, vjust=-2, fontface="bold", family="Helvetica") +
  geom_text(data=filter(gap, Type=="web"),
            aes(x=Befürworter*100, y=Type, label="Befürworter"),
            color= "#06D6A0", size=3.5, vjust=-2, fontface="bold", family="Helvetica") +
  geom_text(data=gap, aes(x=Gegner*100, y=Type, label=percent_first(Gegner)),
            color="#EF476F", size=3, vjust=2.8) +
  geom_text(data=gap, color="#06D6A0", size=3, vjust=2.8,
            aes(x=Befürworter*100, y=Type, label=percent_first(Befürworter))) +
  geom_rect(data=gap, aes(xmin=110, xmax=130, ymin=-Inf, ymax=Inf), fill="#efefe3") + 
  geom_text(data=gap, aes(label=percent_first(gap_b_g), y=Type, x=120), fontface="bold", size=4.5, family="Helvetica") + 
  geom_text(data=filter(gap, Type=="web"), aes(x=120, y=Type, label="DIFF"),
                     color="#7a7d7e", size=4, vjust=-2, fontface="bold", family="Helvetica") +
  scale_x_continuous(expand=c(0,0), limits=c(0, 130), breaks = c(0, 50, 100)) +
  labs(x=NULL, y=NULL,
       caption="Daten: Forschungsstelle sotomo (Corona-Monitor, Welle 4, 2020)")+ 
  theme_bw(base_family="Helvetica") + 
  theme(panel.grid.major=element_blank())+ 
  theme(panel.grid.minor=element_blank())+ 
  theme(panel.border=element_blank())+ 
  theme(plot.title=element_text(face="bold", size = 18, hjust = 0))+ 
  theme(plot.subtitle=element_text(face="italic", size=12, margin=margin(b=12)))+ 
  theme(plot.caption=element_text(size=9, margin=margin(t=12), color="#7a7d7e")) +
  scale_y_discrete(labels = c("Offizielle Warn- und\nInformations-Apps\n(Alertswiss usw.)", "Hausarzt/ Hausärztin", "Klassische Medien", "Soziale Medien", "Persönliches\nUmfeld", "Webseiten von\nstaatlichen\nOrganisationen\n(BAG usw.)")) + 
  
  # Annotation in Grafik
  geom_label(aes(x = 60, y = 4.5, 
                 label = "Gegner stufen soziale Medien\nund das persönliche Umfeld\nwichtiger ein (als Befürworter)"), 
             lineheight = 1.2,
             hjust = 0,
             vjust = 0.5,
             colour = "#555555", 
             fill = "white", 
             label.size = NA, 
             family="Helvetica", 
             size = 4) +
  geom_curve(aes(x = 60, y = 4.5, xend = 34, yend = 4), 
             colour = "#555555", 
             size=0.1, 
             curvature = -0.3,
             arrow = arrow(length = unit(0.02, "npc"))) +
  geom_curve(aes(x = 60, y = 4.6, xend = 35.5, yend = 5), 
             colour = "#555555", 
             size=0.1, 
             curvature = -0.3,
             arrow = arrow(length = unit(0.02, "npc")))

ggsave(height = 7, width = 11,filename = "Dumbbell Plot", device='png', dpi=300)