Die Nullhypothese (H0) geht davon aus, dass kein statistisch signifikanter linearer Zusammenhang besteht. Die Alternativhypothese (H1) nimmt an, dass größere Klassen mit einem niedrigeren Förderbedarf einhergehen
#DATEN EINLESEN UND VORBEREITEN/BEREINIGEN
# Pakete laden
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.2 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readr)
library(ggplot2)
library(kableExtra)
##
## Attaching package: 'kableExtra'
##
## The following object is masked from 'package:dplyr':
##
## group_rows
library(corrr)
library(broom)
library(ggrepel)
library(scales)
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
# Daten einlesen
klassengroesse <- read_delim("/Users/yaren/Downloads/durchschnittliche_klassengroesse.csv",
delim = ";",
locale = locale(encoding = "latin1"),
show_col_types = FALSE)
foerderbedarf <- read_csv("/Users/yaren/Downloads/foerderbedarf.csv",
locale = locale(encoding = "UTF-8"),
show_col_types = FALSE)
## New names:
## • `` -> `...1`
str(klassengroesse)
## spc_tbl_ [72 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ Kreis/ kreisfreie Stadt: chr [1:72] "Kiel" NA NA NA ...
## $ Schule : chr [1:72] "Ellerbeker Schule" "Theodor-Storm-Gemeinschaftsschule" "Lilli-Martius-Schule" "Friedrich-Junge-Gemeinschaftsschule Schreventeich/Wik" ...
## $ Ort : chr [1:72] "Kiel" "Kiel" "Kiel" "Kiel" ...
## $ SuS (inkl.DaZ) : num [1:72] 198 119 236 97 133 210 228 158 203 163 ...
## - attr(*, "spec")=
## .. cols(
## .. `Kreis/ kreisfreie Stadt` = col_character(),
## .. Schule = col_character(),
## .. Ort = col_character(),
## .. `SuS (inkl.DaZ)` = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
#spc_tbl_ [72 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
#$ Kreis/ kreisfreie Stadt: chr [1:72] "Kiel" NA NA NA ...
# $ Schule : chr [1:72] "Ellerbeker Schule" "Theodor-Storm-Gemeinschaftsschule" "Lilli-Martius-Schule" "Friedrich-Junge-Gemeinschaftsschule Schreventeich/Wik" ...
# $ Ort : chr [1:72] "Kiel" "Kiel" "Kiel" "Kiel" ...
# $ SuS (inkl.DaZ) : num [1:72] 198 119 236 97 133 210 228 158 203 163 ...
# - attr(*, "spec")=
# .. cols(
# .. `Kreis/ kreisfreie Stadt` = col_character(),
# .. Schule = col_character(),
# .. Ort = col_character(),
# .. `SuS (inkl.DaZ)` = col_double()
# .. )
# - attr(*, "problems")=<externalptr>
head(klassengroesse)
## # A tibble: 6 × 4
## `Kreis/ kreisfreie Stadt` Schule Ort `SuS (inkl.DaZ)`
## <chr> <chr> <chr> <dbl>
## 1 Kiel Ellerbeker Schule Kiel 198
## 2 <NA> Theodor-Storm-Gemeinschaftss… Kiel 119
## 3 <NA> Lilli-Martius-Schule Kiel 236
## 4 <NA> Friedrich-Junge-Gemeinschaft… Kiel 97
## 5 <NA> Klaus-Groth-Schule mit Grund… Kiel 133
## 6 <NA> Hermann-Löns-Schule Kiel 210
# A tibble: 6 × 4
# `Kreis/ kreisfreie Stadt` Schule Ort `SuS (inkl.DaZ)`
# <chr> <chr> <chr> # <dbl>
# 1 Kiel Ellerbeker Schule Kiel # 198
# 2 NA Theodor-Storm-Gemeinschaftsschule Kiel # 119
# 3 NA Lilli-Martius-Schule Kiel # 236
# 4 NA Friedrich-Junge-Gemeinschaftsschule … Kiel 97
# 5 NA Klaus-Groth-Schule mit Grundschulteil Kiel 133
# 6 NA Hermann-Löns-Schule Kiel 210
summary(klassengroesse)
## Kreis/ kreisfreie Stadt Schule Ort SuS (inkl.DaZ)
## Length:72 Length:72 Length:72 Min. : 1.0
## Class :character Class :character Class :character 1st Qu.:150.2
## Mode :character Mode :character Mode :character Median :202.0
## Mean :205.2
## 3rd Qu.:261.5
## Max. :458.0
# Kreis/ kreisfreie Stadt Schule Ort SuS (inkl.DaZ)
# Length:72 Length:72 Length:72 Min. : 1.0
# Class :character Class :character Class :character 1st Qu.:150.2
# Mode :character Mode :character Mode :character Median :202.0
# mean :205.2
# 3rd Qu.:261.5
# Max. :458.0
klassengroesse[!complete.cases(klassengroesse), ]
## # A tibble: 58 × 4
## `Kreis/ kreisfreie Stadt` Schule Ort `SuS (inkl.DaZ)`
## <chr> <chr> <chr> <dbl>
## 1 <NA> Theodor-Storm-Gemeinschafts… Kiel 119
## 2 <NA> Lilli-Martius-Schule Kiel 236
## 3 <NA> Friedrich-Junge-Gemeinschaf… Kiel 97
## 4 <NA> Klaus-Groth-Schule mit Grun… Kiel 133
## 5 <NA> Hermann-Löns-Schule Kiel 210
## 6 <NA> Max-Tau-Schule Kiel 228
## 7 <NA> St. Jürgen Grund- und Gemei… Lübe… 203
## 8 <NA> Julius-Leber-Schule Lübe… 163
## 9 <NA> Schule Tremser Teich Lübe… 263
## 10 <NA> Trave-Grund- und Gemeinscha… Lübe… 151
## # ℹ 48 more rows
# A tibble: 58 × 4
# `Kreis/ kreisfreie Stadt` Schule Ort `SuS (inkl.DaZ)`
# <chr> <chr> <chr> <dbl>
# 1 NA Theodor-Storm-Gemeinschaftsschule Kiel 119
# 2 NA Lilli-Martius-Schule Kiel 236
# 3 NA Friedrich-Junge-Gemeinschaftsschule… Kiel 97
# 4 NA Klaus-Groth-Schule mit Grundschulte… Kiel 133
# 5 NA Hermann-Löns-Schule Kiel 210
# 6 NA Max-Tau-Schule Kiel 228
# 7 NA St. Jürgen Grund- und Gemeinschafts… Lübe… 203
# 8 NA Julius-Leber-Schule Lübe… 163
# 9 NA Schule Tremser Teich Lübe… 263
# 10 NA Trave-Grund- und Gemeinschaftsschule Lübe… 151
# ℹ 48 more rows
# ℹ Use `print(n = ...)` to see more rows
str(foerderbedarf)
## spc_tbl_ [160 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ ...1 : chr [1:160] "Schleswig-Holstein" "Schleswig-Holstein" "Schleswig-Holstein" "Schleswig-Holstein" ...
## $ Förderschwerpunkt: chr [1:160] "Lernen" "Sprache" "Emotionale und soziale Entwicklung" "Geistige Entwicklung" ...
## $ Jgst. 1 : num [1:160] 31 217 27 57 45 25 20 24 1 447 ...
## $ Jgst. 2 : num [1:160] 67 299 54 89 57 26 13 52 7 664 ...
## $ Jgst. 3 : num [1:160] 552 74 79 62 65 35 16 47 3 933 ...
## $ Jgst. 4 : num [1:160] 895 56 116 93 57 ...
## $ gesamt : num [1:160] 1545 646 276 301 224 ...
## - attr(*, "spec")=
## .. cols(
## .. ...1 = col_character(),
## .. Förderschwerpunkt = col_character(),
## .. `Jgst. 1` = col_double(),
## .. `Jgst. 2` = col_double(),
## .. `Jgst. 3` = col_double(),
## .. `Jgst. 4` = col_double(),
## .. gesamt = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
# spc_tbl_ [160 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
# $ ...1 : chr [1:160] "Schleswig-Holstein" "Schleswig-Holstein" "Schleswig-Holstein" "Schleswig-Holstein" ...
# $ Förderschwerpunkt: chr [1:160] "Lernen" "Sprache" "Emotionale und soziale Entwicklung" "Geistige Entwicklung" ...
# $ Jgst. 1 : num [1:160] 31 217 27 57 45 25 20 24 1 447 ...
# $ Jgst. 2 : num [1:160] 67 299 54 89 57 26 13 52 7 664 ...
# $ Jgst. 3 : num [1:160] 552 74 79 62 65 35 16 47 3 933 ...
# $ Jgst. 4 : num [1:160] 895 56 116 93 57 ...
# $ gesamt : num [1:160] 1545 646 276 301 224 ...
# - attr(*, "spec")=
# .. cols(
# .. ...1 = col_character(),
# .. Förderschwerpunkt = col_character(),
# .. `Jgst. 1` = col_double(),
# .. `Jgst. 2` = col_double(),
# .. `Jgst. 3` = col_double(),
# .. `Jgst. 4` = col_double(),
# .. gesamt = col_double()
# .. )
# - attr(*, "problems")=<externalptr>
head(foerderbedarf)
## # A tibble: 6 × 7
## ...1 Förderschwerpunkt `Jgst. 1` `Jgst. 2` `Jgst. 3` `Jgst. 4` gesamt
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Schleswig-Ho… Lernen 31 67 552 895 1545
## 2 Schleswig-Ho… Sprache 217 299 74 56 646
## 3 Schleswig-Ho… Emotionale und s… 27 54 79 116 276
## 4 Schleswig-Ho… Geistige Entwick… 57 89 62 93 301
## 5 Schleswig-Ho… Körperliche und … 45 57 65 57 224
## 6 Schleswig-Ho… Hören 25 26 35 39 125
# A tibble: 6 × 7
# ...1 Förderschwerpunkt `Jgst. 1` `Jgst. 2` `Jgst. 3` `Jgst. 4` gesamt
# <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Schleswig-Holstein Lernen 31 67 552 895 1545
# 2 Schleswig-Holstein Sprache 217 299 74 56 646
# 3 Schleswig-Holstein Emotionale und sozi… 27 54 79 116 276
# 4 Schleswig-Holstein Geistige Entwicklung 57 89 62 93 301
# 5 Schleswig-Holstein Körperliche und mot… 45 57 65 57 224
# 6 Schleswig-Holstein Hören 25 26 35 39 125
summary(foerderbedarf)
## ...1 Förderschwerpunkt Jgst. 1 Jgst. 2
## Length:160 Length:160 Min. : 0.00 Min. : 0.0
## Class :character Class :character 1st Qu.: 0.00 1st Qu.: 1.0
## Mode :character Mode :character Median : 2.00 Median : 3.0
## Mean : 11.18 Mean : 16.6
## 3rd Qu.: 6.25 3rd Qu.: 9.0
## Max. :447.00 Max. :664.0
## Jgst. 3 Jgst. 4 gesamt
## Min. : 0.00 Min. : 0.00 Min. : 0.0
## 1st Qu.: 1.00 1st Qu.: 1.00 1st Qu.: 5.0
## Median : 3.00 Median : 5.00 Median : 15.0
## Mean : 23.32 Mean : 34.10 Mean : 85.2
## 3rd Qu.: 16.00 3rd Qu.: 20.25 3rd Qu.: 68.0
## Max. :933.00 Max. :1364.00 Max. :3408.0
# ...1 Förderschwerpunkt Jgst. 1 Jgst. 2
# Length:160 Length:160 Min. : 0.00 Min. : 0.0
# Class :character Class :character 1st Qu.: 0.00 1st Qu.: 1.0
# Mode :character Mode :character Median : 2.00 Median : 3.0
# mean : 11.18 mean : 16.6
# 3rd Qu.: 6.25 3rd Qu.: 9.0
# Max. :447.00 Max. :664.0
# Jgst. 3 Jgst. 4 gesamt
# Min. : 0.00 Min. : 0.00 Min. : 0.0
# 1st Qu.: 1.00 1st Qu.: 1.00 1st Qu.: 5.0
# Median : 3.00 Median : 5.00 Median : 15.0
# mean : 23.32 mean : 34.10 mean : 85.2
# 3rd Qu.: 16.00 3rd Qu.: 20.25 3rd Qu.: 68.0
# Max. :933.00 Max. :1364.00 Max. :3408.0
Hier wird die Struktur der Klassengrößendaten inspiziert: Anzahl der Variablen, Datentypen und erste Zeilen. Fehlende Werte werden identifiziert, vor allem bei der Kreisbezeichnung.
klassengroesse_clean <- klassengroesse %>%
# Gesamtsumme herausfiltern
filter(!(`Kreis/ kreisfreie Stadt` %in% c("Gesamt SH", NA) & is.na(Schule))) %>%
# Fehlende Kreisnamen ergänzen (forward fill)
fill(`Kreis/ kreisfreie Stadt`, .direction = "down") %>%
# Spalten umbenennen für bessere Handhabung
rename(
kreis = `Kreis/ kreisfreie Stadt`,
schule = `Schule`,
ort = `Ort`,
schueler_anzahl = `SuS (inkl.DaZ)`
) %>%
# Schülerzahl als numerisch definieren und gültige Daten filtern
mutate(schueler_anzahl = as.numeric(schueler_anzahl)) %>%
filter(!is.na(schueler_anzahl), schueler_anzahl > 0, !is.na(kreis))
1
## [1] 1
Es wurden Gesamtsummen und leere Zeilen entfernt. Fehlende Kreisnamen wurden mit dem Wert der vorherigen Zeile ausgefüllt und Variablen wurden umbenannt.Zudem wurden ungültige und Nullwerte herausgefiltert.
foerderbedarf_clean <- foerderbedarf %>%
# Erste Spalte korrekt benennen
rename(region = 1) %>%
# Nur Kreisdaten (ohne Gesamtsumme für Schleswig-Holstein)
filter(region != "Schleswig-Holstein") %>%
# Nur Zeilen mit "Alle Förderschwerpunkte" für Gesamtübersicht
filter(Förderschwerpunkt == "Alle Förderschwerpunkte") %>%
# Relevante Spalten auswählen
select(region, gesamt) %>%
rename(kreis = region, foerderbedarf_gesamt = gesamt)
Hier wird nur der Gesamt-Förderbedarf pro Kreis extrahiert – unabhängig vom Förderschwerpunkt – und auf Kreisnamen reduziert.
klassengroesse_kreis <- klassengroesse_clean %>%
group_by(kreis) %>%
summarise(
anzahl_schulen = n(),
schueler_gesamt_kreis = sum(schueler_anzahl, na.rm = TRUE),
durchschnitt_schueler_pro_schule = mean(schueler_anzahl, na.rm = TRUE),
median_schueler_pro_schule = median(schueler_anzahl, na.rm = TRUE),
.groups = 'drop'
) %>%
mutate(
geschaetzte_klassen_pro_schule = durchschnitt_schueler_pro_schule / 25,
geschaetzte_klassengroesse = ifelse(
geschaetzte_klassen_pro_schule >= 1,
durchschnitt_schueler_pro_schule / round(geschaetzte_klassen_pro_schule),
durchschnitt_schueler_pro_schule
)
)
# Datensätze verknüpfen
analyse_daten <- klassengroesse_kreis %>%
inner_join(foerderbedarf_clean, by = "kreis") %>%
# Förderanteil berechnen
mutate(
foerderanteil_prozent = (foerderbedarf_gesamt / schueler_gesamt_kreis) * 100
) %>%
# Nur vollständige Fälle behalten
filter(!is.na(foerderanteil_prozent), !is.na(geschaetzte_klassengroesse))
# print("\n=== FINALE ANALYSEDATEN ===")
Die beiden Datensätze werden auf Kreisebene aggregiert und verknüpft. Es werden geschätzte Klassengrößen berechnet (Annahme: 25 Schüler pro Klasse). Zusätzlich wird der prozentuale Anteil der Schüler mit Förderbedarf je Kreis ermittelt.
# print(analyse_daten)
# A tibble: 13 × 9
# kreis anzahl_schulen schueler_gesamt_kreis durchschnitt_schueler_pr…¹
# <chr> <int> <dbl> <dbl>
# 1 Dithmarschen 5 908 182.
# 2 Hzgt. Lauenburg 3 953 318.
# 3 Kiel 7 1221 174.
# 4 Lübeck 11 2028 184.
# 5 Neumünster 2 366 183
# 6 Nordfriesland 9 696 77.3
# 7 Ostholstein 4 968 242
# 8 Pinneberg 6 1153 192.
# 9 Plön 3 612 204
# 10 Rendsburg-Eckernförde 6 1723 287.
# 11 Segeberg 7 1784 255.
# 12 Steinburg 1 215 215
# 13 Stormarn 1 374 374
# ℹ abbreviated name: ¹durchschnitt_schueler_pro_schule
# ℹ 5 more variables: median_schueler_pro_schule <dbl>,
# geschaetzte_klassen_pro_schule <dbl>, geschaetzte_klassengroesse <dbl>,
# foerderbedarf_gesamt <dbl>, foerderanteil_prozent <dbl>
# print(paste("Anzahl Kreise in der Analyse:", nrow(analyse_daten)))
desc_stats <- analyse_daten %>%
summarise(
# Schülerzahlen
mean_schueler_pro_schule = mean(durchschnitt_schueler_pro_schule, na.rm = TRUE),
sd_schueler_pro_schule = sd(durchschnitt_schueler_pro_schule, na.rm = TRUE),
min_schueler_pro_schule = min(durchschnitt_schueler_pro_schule, na.rm = TRUE),
max_schueler_pro_schule = max(durchschnitt_schueler_pro_schule, na.rm = TRUE),
# Klassengröße (geschätzt)
mean_klassengroesse = mean(geschaetzte_klassengroesse, na.rm = TRUE),
sd_klassengroesse = sd(geschaetzte_klassengroesse, na.rm = TRUE),
min_klassengroesse = min(geschaetzte_klassengroesse, na.rm = TRUE),
max_klassengroesse = max(geschaetzte_klassengroesse, na.rm = TRUE),
# Förderanteil
mean_foerderanteil = mean(foerderanteil_prozent, na.rm = TRUE),
sd_foerderanteil = sd(foerderanteil_prozent, na.rm = TRUE),
min_foerderanteil = min(foerderanteil_prozent, na.rm = TRUE),
max_foerderanteil = max(foerderanteil_prozent, na.rm = TRUE)
)
#DESKRIPTIVE STATISTIK
# print(desc_stats)
# A tibble: 1 × 13
# mean_schueler_pro_schule sd_schueler_pro_schule min_schueler_pro_schule
# <dbl> <dbl> <dbl>
# 1 222. 74.7 77.3
# ℹ 10 more variables: max_schueler_pro_schule <dbl>, mean_klassengroesse <dbl>,
# sd_klassengroesse <dbl>, min_klassengroesse <dbl>, max_klassengroesse <dbl>,
# mean_foerderanteil <dbl>, sd_foerderanteil <dbl>, min_foerderanteil <dbl>,
# max_foerderanteil <dbl>, n_kreise <int>
Die Analyse umfasst 13 Kreise mit insgesamt 71 Schulen und 14.778 Schülern. Die durchschnittliche Schülerzahl pro Schule betrug 222 ± 74,7 Schüler, während die geschätzte Klassengröße bei 25,2 ± 0,861 Schülern lag. Der Anteil der Schüler mit Förderbedarf variierte stark zwischen 12,2% und 74,9%, mit einem Mittelwert von 30,3 ± 19,3%.
Das heißt: Obwohl die durchschnittlichen Klassengrößen mit 25,2 Schülern (± 0,9) sehr ähnlich sind, schwankt der Anteil der Schüler mit Förderbedarf zwischen nur 12,2% und fast 75%. Das zeigt, dass Klassenstärke allein nicht erklärt, warum manche Kreise viel mehr Förderbedarf ausweisen als andere.
library(ggplot2)
library(ggrepel)
korrelation <- cor.test(analyse_daten$geschaetzte_klassengroesse,
analyse_daten$foerderanteil_prozent,
method = "pearson")
r_val <- as.numeric(korrelation$estimate)
p_val <- korrelation$p.value
p_text <- if (p_val < 0.001) "< 0.001" else format(round(p_val, 3), nsmall = 3)
label_rp <- paste0("Pearson r = ", round(r_val, 3), "\np = ", p_text)
x_pos <- max(analyse_daten$geschaetzte_klassengroesse, na.rm = TRUE) * 0.95
y_pos <- max(analyse_daten$foerderanteil_prozent, na.rm = TRUE) * 0.95
p_scatter_main <- ggplot(analyse_daten,
aes(x = geschaetzte_klassengroesse,
y = foerderanteil_prozent)) +
geom_point(aes(size = schueler_gesamt_kreis), color = "steelblue", alpha = 0.75) +
geom_smooth(method = "lm", se = TRUE, color = "red", alpha = 0.3) +
geom_text_repel(aes(label = kreis), size = 3, max.overlaps = 20,
box.padding = 0.5, point.padding = 0.3) +
scale_size_area("Gesamtschüler\nim Kreis", max_size = 12,
labels = function(x) format(x, big.mark = ".", decimal.mark = ",")) +
annotate("label", x = x_pos, y = y_pos, label = label_rp, hjust = 1, vjust = 1,
fill = "white", alpha = 0.9, size = 3.5, label.padding = unit(0.3, "lines")) +
labs(title = "Zusammenhang zwischen Klassengröße und Förderbedarf",
subtitle = paste0("Schleswig-Holstein, ", nrow(analyse_daten), " Kreise"),
x = "Geschätzte durchschnittliche Klassengröße",
y = "Anteil Schüler mit Förderbedarf (%)",
caption = "Punktgröße = Gesamtschülerzahl im Kreis\nKlassengröße geschätzt basierend auf Schülerzahl pro Schule") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold", size = 14),
plot.subtitle = element_text(size = 12),
legend.position = "bottom"
)
print(p_scatter_main)
## `geom_smooth()` using formula = 'y ~ x'
Der Scatterplot zeigt keine klare Trendlinie zwischen Klassengröße und Förderanteil.
p_hist_klassen <- ggplot(analyse_daten, aes(x = geschaetzte_klassengroesse)) +
geom_histogram(binwidth = 2, color = "black", fill = "#4B9CD3", alpha = 0.8) +
geom_vline(aes(xintercept = mean(geschaetzte_klassengroesse)),
color = "red", linetype = "dashed", linewidth = 1) +
geom_vline(aes(xintercept = median(geschaetzte_klassengroesse)),
color = "darkgreen", linetype = "dotted", linewidth = 1) +
annotate("text", x = mean(analyse_daten$geschaetzte_klassengroesse) + 1,
y = 2.5, label = paste0("μ = ", round(mean(analyse_daten$geschaetzte_klassengroesse), 1)),
color = "red", hjust = 0, size = 3.5) +
annotate("text", x = median(analyse_daten$geschaetzte_klassengroesse) - 1,
y = 2, label = paste0("Median = ", round(median(analyse_daten$geschaetzte_klassengroesse), 1)),
color = "darkgreen", hjust = 1, size = 3.5) +
labs(title = "Verteilung der geschätzten Klassengrößen",
subtitle = "Basierend auf durchschnittlicher Schülerzahl pro Schule",
x = "Geschätzte Klassengröße", y = "Anzahl Kreise") +
theme_minimal() +
theme(plot.title = element_text(face = "bold"))
print(p_hist_klassen)
p_hist_foerder <- ggplot(analyse_daten, aes(x = foerderanteil_prozent)) +
geom_histogram(binwidth = 10, color = "black", fill = "#FFA756", alpha = 0.8) +
geom_vline(aes(xintercept = mean(foerderanteil_prozent)),
color = "red", linetype = "dashed", linewidth = 1) +
geom_vline(aes(xintercept = median(foerderanteil_prozent)),
color = "darkgreen", linetype = "dotted", linewidth = 1) +
annotate("text", x = mean(analyse_daten$foerderanteil_prozent) + 5,
y = 2.5, label = paste0("μ = ", round(mean(analyse_daten$foerderanteil_prozent), 1), "%"),
color = "red", hjust = 0, size = 3.5) +
annotate("text", x = median(analyse_daten$foerderanteil_prozent) - 5,
y = 2, label = paste0("Median = ", round(median(analyse_daten$foerderanteil_prozent), 1), "%"),
color = "darkgreen", hjust = 1, size = 3.5) +
labs(title = "Verteilung des Förderanteils",
subtitle = "Anteil Schüler mit Förderbedarf pro Kreis",
x = "Anteil Förderbedarf (%)", y = "Anzahl Kreise") +
theme_minimal() +
theme(plot.title = element_text(face = "bold"))
print(p_hist_foerder)
Die beiden Histogramme zeigen, dass Klassengrößen eng beieinander liegen, während Förderanteile stark streuen.
p_boxplot <- analyse_daten %>%
select(kreis, geschaetzte_klassengroesse, foerderanteil_prozent) %>%
pivot_longer(cols = c(geschaetzte_klassengroesse, foerderanteil_prozent),
names_to = "variable", values_to = "wert") %>%
mutate(variable = case_when(
variable == "geschaetzte_klassengroesse" ~ "Klassengröße",
variable == "foerderanteil_prozent" ~ "Förderanteil (%)"
)) %>%
ggplot(aes(x = variable, y = wert)) +
geom_boxplot(fill = "lightblue", alpha = 0.7) +
geom_jitter(width = 0.2, alpha = 0.6, color = "darkblue") +
facet_wrap(~variable, scales = "free_y") +
labs(title = "Verteilungsübersicht der Hauptvariablen",
x = "", y = "Wert") +
theme_minimal() +
theme(plot.title = element_text(face = "bold"))
print(p_boxplot)
Die Boxplots machen die homogene Verteilung der Klassengrößen und die heterogenen Förderanteile auf einen Blick sichtbar.
# Shapiro-Wilk Test für geschätzte Klassengröße
shapiro_klasse <- shapiro.test(analyse_daten$geschaetzte_klassengroesse)
cat("Shapiro-Wilk Test für geschätzte Klassengröße:\n")
## Shapiro-Wilk Test für geschätzte Klassengröße:
print(shapiro_klasse)
##
## Shapiro-Wilk normality test
##
## data: analyse_daten$geschaetzte_klassengroesse
## W = 0.91846, p-value = 0.2391
# Interpretation
if(shapiro_klasse$p.value > 0.05) {
cat("-> Die geschätzte Klassengröße ist vermutlich normalverteilt (p =", round(shapiro_klasse$p.value, 4), ")\n\n")
} else {
cat("-> Die geschätzte Klassengröße ist nicht normalverteilt (p =", round(shapiro_klasse$p.value, 4), ")\n\n")
}
## -> Die geschätzte Klassengröße ist vermutlich normalverteilt (p = 0.2391 )
# Shapiro-Wilk Test für Förderanteil
shapiro_foerder <- shapiro.test(analyse_daten$foerderanteil_prozent)
cat("Shapiro-Wilk Test für Förderanteil:\n")
## Shapiro-Wilk Test für Förderanteil:
print(shapiro_foerder)
##
## Shapiro-Wilk normality test
##
## data: analyse_daten$foerderanteil_prozent
## W = 0.78112, p-value = 0.004102
# Interpretation
if(shapiro_foerder$p.value > 0.05) {
cat("-> Der Förderanteil ist vermutlich normalverteilt (p =", round(shapiro_foerder$p.value, 4), ")\n")
} else {
cat("-> Der Förderanteil ist nicht normalverteilt (p =", round(shapiro_foerder$p.value, 4), ")\n")
}
## -> Der Förderanteil ist nicht normalverteilt (p = 0.0041 )
Die geschätzten Klassengrößen folgen einer Normalverteilung (Shapiro-Wilk p = 0,239), sodass klassische, parametrische Verfahren wie die Pearson-Korrelation angemessen sind. Der Förderanteil ist dagegen nicht normalverteilt (p = 0,004), weshalb zusätzlich ein nicht-parametrischer Spearman-Test eingesetzt wurde. Hier also keine Normalverteilung.
# [1] "\n=== KORRELATIONSANALYSE ==="
# > # Hauptkorrelation: Klassengröße vs. Förderanteil
# print("1. Geschätzte Klassengröße vs. Förderanteil:")
# [1] "1. Geschätzte Klassengröße vs. Förderanteil:"
# > korr_hauptfrage <- cor.test(analyse_daten$geschaetzte_klassengroesse,
# + analyse_daten$foerderanteil_prozent,
# + method = "pearson")
# print(korr_hauptfrage)
# Pearson's product-moment correlation
# data: analyse_daten$geschaetzte_klassengroesse and analyse_daten$foerderanteil_prozent
# t = -1.2094, df = 11, p-value = 0.2519
# alternative hypothesis: true correlation is not equal to 0
# 95 percent confidence interval:
# -0.7516785 0.2569009
# sample estimates:
# cor
# -0.3425755
# > print(" Spearman (nicht-parametrisch):")
# [1] " Spearman (nicht-parametrisch):"
# > korr_hauptfrage_spear <- cor.test(analyse_daten$geschaetzte_klassengroesse,
# + analyse_daten$foerderanteil_prozent,
# + method = "spearman")
# print(korr_hauptfrage_spear)
# Spearman's rank correlation rho
# data: analyse_daten$geschaetzte_klassengroesse and analyse_daten$foerderanteil_prozent
# S = 390, p-value = 0.8206
# alternative hypothesis: true rho is not equal to 0
# sample estimates:
# rho
-0.07142857
## [1] -0.07142857
# > # Alternative: Schülerzahl vs. Förderanteil
# print("\n2. Durchschnittliche Schülerzahl vs. Förderanteil:")
# [1] "\n2. Durchschnittliche Schülerzahl vs. Förderanteil:"
# korr_schueler <- cor.test(analyse_daten$durchschnitt_schueler_pro_schule,
# + analyse_daten$foerderanteil_prozent,
# + method = "pearson")
# > print(korr_schueler)
# Pearson's product-moment correlation
# data: analyse_daten$durchschnitt_schueler_pro_schule and analyse_daten$foerderanteil_prozent
# t = 0.97595, df = 11, p-value = 0.3501
# alternative hypothesis: true correlation is not equal to 0
# 95 percent confidence interval:
# -0.3181822 0.7211163
# sample estimates:
cor
## function (x, y = NULL, use = "everything", method = c("pearson",
## "kendall", "spearman"))
## {
## na.method <- pmatch(use, c("all.obs", "complete.obs", "pairwise.complete.obs",
## "everything", "na.or.complete"))
## if (is.na(na.method))
## stop("invalid 'use' argument")
## method <- match.arg(method)
## if (is.data.frame(y))
## y <- as.matrix(y)
## if (is.data.frame(x))
## x <- as.matrix(x)
## if (!is.matrix(x) && is.null(y))
## stop("supply both 'x' and 'y' or a matrix-like 'x'")
## if (!(is.numeric(x) || is.logical(x)))
## stop("'x' must be numeric")
## stopifnot(is.atomic(x))
## if (!is.null(y)) {
## if (!(is.numeric(y) || is.logical(y)))
## stop("'y' must be numeric")
## stopifnot(is.atomic(y))
## }
## Rank <- function(u) {
## if (length(u) == 0L)
## u
## else if (is.matrix(u)) {
## if (nrow(u) > 1L)
## apply(u, 2L, rank, na.last = "keep")
## else row(u)
## }
## else rank(u, na.last = "keep")
## }
## if (method == "pearson")
## .Call(C_cor, x, y, na.method, FALSE)
## else if (na.method %in% c(2L, 5L)) {
## if (is.null(y)) {
## .Call(C_cor, Rank(na.omit(x)), NULL, na.method, method ==
## "kendall")
## }
## else {
## nas <- attr(na.omit(cbind(x, y)), "na.action")
## dropNA <- function(x, nas) {
## if (length(nas)) {
## if (is.matrix(x))
## x[-nas, , drop = FALSE]
## else x[-nas]
## }
## else x
## }
## .Call(C_cor, Rank(dropNA(x, nas)), Rank(dropNA(y,
## nas)), na.method, method == "kendall")
## }
## }
## else if (na.method != 3L) {
## x <- Rank(x)
## if (!is.null(y))
## y <- Rank(y)
## .Call(C_cor, x, y, na.method, method == "kendall")
## }
## else {
## if (is.null(y)) {
## ncy <- ncx <- ncol(x)
## if (ncx == 0)
## stop("'x' is empty")
## r <- matrix(0, nrow = ncx, ncol = ncy)
## for (i in seq_len(ncx)) {
## for (j in seq_len(i)) {
## x2 <- x[, i]
## y2 <- x[, j]
## ok <- complete.cases(x2, y2)
## x2 <- rank(x2[ok])
## y2 <- rank(y2[ok])
## r[i, j] <- if (any(ok))
## .Call(C_cor, x2, y2, 1L, method == "kendall")
## else NA
## }
## }
## r <- r + t(r) - diag(diag(r))
## rownames(r) <- colnames(x)
## colnames(r) <- colnames(x)
## r
## }
## else {
## if (length(x) == 0L || length(y) == 0L)
## stop("both 'x' and 'y' must be non-empty")
## matrix_result <- is.matrix(x) || is.matrix(y)
## if (!is.matrix(x))
## x <- matrix(x, ncol = 1L)
## if (!is.matrix(y))
## y <- matrix(y, ncol = 1L)
## ncx <- ncol(x)
## ncy <- ncol(y)
## r <- matrix(0, nrow = ncx, ncol = ncy)
## for (i in seq_len(ncx)) {
## for (j in seq_len(ncy)) {
## x2 <- x[, i]
## y2 <- y[, j]
## ok <- complete.cases(x2, y2)
## x2 <- rank(x2[ok])
## y2 <- rank(y2[ok])
## r[i, j] <- if (any(ok))
## .Call(C_cor, x2, y2, 1L, method == "kendall")
## else NA
## }
## }
## rownames(r) <- colnames(x)
## colnames(r) <- colnames(y)
## if (matrix_result)
## r
## else drop(r)
## }
## }
## }
## <bytecode: 0x13695eff8>
## <environment: namespace:stats>
0.2822929
## [1] 0.2822929
Die Pearson-Korrelation zwischen Klassengröße und Förderanteil betrug r = –0,343 (p = 0,252), die Spearman-Rangkorrelation ρ = –0,071 (p = 0,821); beide Zusammenhänge sind statistisch nicht signifikant.Ein negativer r-Wert bedeutet zwar einen leichten Trend zu weniger Förderbedarf bei größeren Klassen, dieser Effekt ist aber statistisch nicht belastbar.
#REGRESSIONSANALYSE
cat("\n=== REGRESSIONSANALYSE ===\n")
##
## === REGRESSIONSANALYSE ===
cat("1. HAUPTMODELL: Klassengröße -> Förderanteil\n")
## 1. HAUPTMODELL: Klassengröße -> Förderanteil
# Lineares Modell erstellen
hauptmodell <- lm(foerderanteil_prozent ~ geschaetzte_klassengroesse, data = analyse_daten)
# Zusammenfassung des Modells
summary_haupt <- summary(hauptmodell)
# Ergebnis ausgeben
print(summary_haupt)
##
## Call:
## lm(formula = foerderanteil_prozent ~ geschaetzte_klassengroesse,
## data = analyse_daten)
##
## Residuals:
## Min 1Q Median 3Q Max
## -25.883 -10.656 -5.692 7.036 34.420
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 224.014 160.233 1.398 0.190
## geschaetzte_klassengroesse -7.683 6.353 -1.209 0.252
##
## Residual standard error: 18.96 on 11 degrees of freedom
## Multiple R-squared: 0.1174, Adjusted R-squared: 0.03712
## F-statistic: 1.463 on 1 and 11 DF, p-value: 0.2519
# Ergebnis (kommentiert als Referenz)
# Call:
# lm(formula = foerderanteil_prozent ~ geschaetzte_klassengroesse, data = analyse_daten)
#
# Residuals:
# Min 1Q Median 3Q Max
# -25.883 -10.656 -5.692 7.036 34.420
#
# Coefficients:
# Estimate Std. Error t value Pr(>|t|)
# (Intercept) 224.014 160.233 1.398 0.190
# geschaetzte_klassengroesse -7.683 6.353 -1.209 0.252
#
# Residual standard error: 18.96 on 11 degrees of freedom
# Multiple R-squared: 0.1174, Adjusted R-squared: 0.03712
# F-statistic: 1.463 on 1 and 11 DF, p-value: 0.2519
Das Regressionsmodell erklärt nur 11,7% der Variation im Förderanteil (R² = 0,1174). Der geschätzte Einfluss der Klassengröße (β = –7,683; p = 0,252) ist nicht signifikant. Das heißt, selbst wenn ich eine lineare Funktion anlege, trägt die Klassengröße kaum zur Vorhersage des Förderanteils bei.
cat("\n2. ALTERNATIVMODELL: Schülerzahl -> Förderanteil\n")
##
## 2. ALTERNATIVMODELL: Schülerzahl -> Förderanteil
alt_modell <- lm(foerderanteil_prozent ~ durchschnitt_schueler_pro_schule, data = analyse_daten)
summary_alt <- summary(alt_modell)
print(summary_alt)
##
## Call:
## lm(formula = foerderanteil_prozent ~ durchschnitt_schueler_pro_schule,
## data = analyse_daten)
##
## Residuals:
## Min 1Q Median 3Q Max
## -21.735 -13.911 0.490 4.339 45.067
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 14.12457 17.45779 0.809 0.436
## durchschnitt_schueler_pro_schule 0.07299 0.07479 0.976 0.350
##
## Residual standard error: 19.36 on 11 degrees of freedom
## Multiple R-squared: 0.07969, Adjusted R-squared: -0.003975
## F-statistic: 0.9525 on 1 and 11 DF, p-value: 0.3501
# Ergebnis als Kommentar:
# Call:
# lm(formula = foerderanteil_prozent ~ durchschnitt_schueler_pro_schule, data = analyse_daten)
#
# Residuals:
# Min 1Q Median 3Q Max
# -21.735 -13.911 0.490 4.339 45.067
#
# Coefficients:
# Estimate Std. Error t value Pr(>|t|)
# (Intercept) 14.12457 17.45779 0.809 0.436
# durchschnitt_schueler_pro_schule 0.07299 0.07479 0.976 0.350
#
# Residual standard error: 19.36 on 11 degrees of freedom
# Multiple R-squared: 0.07969, Adjusted R-squared: -0.003975
# F-statistic: 0.9525 on 1 and 11 DF, p-value: 0.3501
Es gibt keine Belege dafür, dass größere oder kleinere Klassen systematisch mehr oder weniger Förderbedarf haben. Schulpolitische Entscheidungen zu Förderressourcen sollten sich nicht allein an der Klassengröße orientieren. Vielmehr müssen andere Faktoren (z. B. regionale Sozialstruktur, spezifische Inklusionspolitik, Förderangebote vor Ort) untersucht werden, um die Ursachen für unterschiedliche Förderbedarfe zu verstehen.
Es besteht also kein signifikanter Zusammenhang zwischen Klassengröße und Förderanteil. Die Nullhypothese H0 wird beibehalten.