# 0. Pakete laden (ggf. vorher installieren) # install.packages(c("ggtext","shadowtext","viridis","showtext","sf", "ggplot2", "dplyr", "rnaturalearth", "rnaturalearthhires")) install.packages("ggnewscale") library(sf) library(ggplot2) library(ggtext) library(dplyr) library(rnaturalearth) library(rnaturalearthhires) library(showtext) library(viridis) library(shadowtext) library(ggnewscale) # Variablen hintergrundfarbe <- "#f2f2f2" # 1 Automatisches Laden von Schriftarten und Fira Sans aktivieren showtext_auto() font_add(family = "Fira Sans", regular = "FiraSans-Regular.ttf") # 2. Geodaten für Deutschland laden germany_states <- ne_states(country = "Germany", returnclass = "sf") # 3. CSV-Daten einlesen inf_einf <- read.csv2("~/Informatik-Monitor/Ländervergleich/BL_Informatik_Einfuehrungsphase_Schularten.csv", stringsAsFactors = FALSE) #colnames(schulsystem_daten) <- c("name", "schulsystem") # ------------------------------------------------------------- # 2) Bestimme pro Bundesland, ob "Wahlpflicht" vorhanden ist. # Wenn ja: IU_Art = "Wahlpflicht", sonst "Pflicht" # ------------------------------------------------------------- inf_einf_art_gruppiert <- inf_einf %>% # Starte mit deinen Daten group_by(Bundesland) %>% # Gruppiere nach Bundesland summarise( IU_Art = if ("Wahlpflicht" %in% IU_Art) { "Wahlpflicht" } else { "Pflicht" } ) # ------------------------------------------------------------- # 3) Verbinde die gewählte IU_Art wieder mit den Originaldaten. # Dadurch behältst du nur die Zeilen mit der passenden IU_Art. # ------------------------------------------------------------- inf_einf_art_gruppiert_gesamt <- inf_einf_art_gruppiert %>% # Nimm die priorisierte Liste left_join(inf_einf, # Füge die Originaldaten an by = c("Bundesland", "IU_Art")) # Verknüpfe auf beide Spalten # ------------------------------------------------------------- # 4) Berechne pro Bundesland den niedrigsten IU_Stunden_min-Wert # NUR aus den Zeilen der gewählten IU_Art. # ------------------------------------------------------------- inf_einf_art_gruppiert_gesamt_kurz <- inf_einf_art_gruppiert_gesamt %>% # Starte mit dem verknüpften Datensatz group_by(Bundesland, IU_Art) %>% # Gruppiere wieder summarise( IU_Stunden_min = min(IU_Stunden_min), # Berechne den minimalen Wert .groups = "drop" # Entferne Gruppierung im Ergebnis ) # # 5) Geodaten mit Einf-Phase-Daten verknüpfen # germany_data <- germany_states %>% # left_join(inf_einf, by = c("name" = "Bundesland")) # 5) Geodaten mit priorisierten Daten verknüpfen germany_data <- germany_states %>% left_join(inf_einf_art_gruppiert_gesamt_kurz, by = c("name" = "Bundesland")) # postal-Kürzel korrigieren: Brandenburg → "BB" germany_data <- germany_data %>% mutate(postal = ifelse(name == "Brandenburg", "BB", postal)) # Nur die Grenzen extrahieren (Linien) grenzen <- germany_data %>% st_geometry() %>% st_cast("MULTIPOLYGON") %>% st_boundary() %>% st_sf() germany_data <- germany_data %>% mutate( IU_Farbe = paste0(IU_Art, "_", IU_Stunden_min) ) farben <- c( "Wahlpflicht_1" = "#fff16f", # helles Gelb "Wahlpflicht_2" = "#ffe601", # mittelgold "Wahlpflicht_3" = "#e8d101", # dunkler Gold-/Orangeton "Pflicht_1" = "#3e609e", # hellblau "Pflicht_2" = "#0e1f51" # kräftiges Dunkelblau ) germany_data <- germany_data %>% mutate( IU_Farbe = ifelse( is.na(IU_Stunden_min) | is.na(IU_Art), NA_character_, # wirklich Character-NA! paste0(IU_Art, "_", IU_Stunden_min) ) ) %>% # Jetzt factorisieren OHNE NA-Level: mutate( IU_Farbe = forcats::fct_drop( # entfernt NA-Level, falls es noch drin ist factor( IU_Farbe, levels = c( "Wahlpflicht_1", "Wahlpflicht_2", "Wahlpflicht_3", "Pflicht_1", "Pflicht_2" ) ) ) ) # Mittelpunkte der BL-Flächenberechnen bundesland_labels <- germany_data %>% mutate(centroid = st_centroid(geometry)) %>% mutate( x = st_coordinates(centroid)[, 1], y = st_coordinates(centroid)[, 2] ) %>% mutate( x = ifelse(name == "Brandenburg", x + 0.5, x), # nach Osten y = ifelse(name == "Brandenburg", y - 0.4, y) # nach Süden ) %>% mutate( x = ifelse(name == "Berlin", x + 0.12, x), # nach Osten y = ifelse(name == "Berlin", y + 0.12, y) # nach Norden ) %>% mutate( x = ifelse(name == "Bremen", x + 0.2, x), # nach Osten y = ifelse(name == "Bremen", y + 0.04, y) # nach Norden ) %>% mutate( x = ifelse(name == "Hamburg", x - 0.05, x), # nach Westen y = ifelse(name == "Hamburg", y - 0.15, y) # nach Süden ) # 5. Karte erzeugen mit viridis & ggnewscale karte <- ggplot() + # Nicht-NA-Flächen mit Farben geom_sf( data = filter(germany_data, !is.na(IU_Farbe)), aes(fill = IU_Farbe), color = NA ) + # NA-Flächen extra füllen geom_sf( data = filter(germany_data, is.na(IU_Farbe)), fill = hintergrundfarbe, color = NA ) + geom_sf( data = grenzen, fill = NA, color = hintergrundfarbe, size = 0.3 ) + coord_sf(expand = FALSE) + geom_shadowtext( data = bundesland_labels, aes(x = x, y = y, label = postal), family = "Fira Sans", size = 3.5, color = hintergrundfarbe, bg.color = "black", bg.r = 0.05, check_overlap = TRUE ) + scale_fill_manual( values = farben, name = "Informatik", labels = c( "Wahlpflicht_1" = "Wahlpflicht: 1 WS", "Wahlpflicht_2" = "Wahlpflicht: 2 WS", "Wahlpflicht_3" = "Wahlpflicht: 3 WS", "Pflicht_1" = "Pflicht: 1 WS", "Pflicht_2" = "Pflicht: 2 WS" ) ) + labs( title = "Informatikunterricht in der Einführungsphase", subtitle = "Informatik in der gymnasialen Oberstufe an allgemeinbildenden Schulen, 2025", caption = "Datenquelle: Informatik-Monitor" ) + theme_minimal() + theme( text = element_text(family = "Fira Sans"), plot.title = element_text(face = "bold", size = 16), plot.subtitle = ggtext::element_markdown(size = 12, lineheight = 1.2), plot.background = element_rect(fill = hintergrundfarbe, color = NA), panel.background = element_rect(fill = hintergrundfarbe, color = NA), legend.background = element_rect(fill = hintergrundfarbe, color = NA), legend.key = element_rect(fill = hintergrundfarbe, color = NA), panel.grid = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), axis.title = element_blank(), legend.position = "bottom", legend.direction = "horizontal", legend.box.just = "right", legend.title = element_blank(), plot.margin = margin(1, 1, 1, 1, unit = "cm"), plot.caption = element_text(margin = margin(t = 15)) ) # 6. Karte anzeigen print(karte) # 7. Karte speichern ggsave( filename = "BL_Oberstufe_IU_Einf_Art_Umfang.svg", plot = karte, path = "~/Informatik-Monitor/Ländervergleich", width = 18, height = 27, unit = "cm", device = "svg" )