Hypothese¶
H1: Es gibt einen Zusammmenhang zwischen der Studierbereitschaft vor dem Auslandsjahr und der Studierbereitschaft nach dem Auslandsjahr.
H0: Es gibt keinen Zusammmenhang zwischen der Studierbereitschaft vor dem Auslandsjahr und der Studierbereitschaft nach dem Auslandsjahr.
Alternativ¶
H0: Beide Variablen sind in der Grundgesamtheit unabhängig voneinander.
H1: Beide Variablen sind in der Grundgesamtheit abhängig voneinander
Vorausetzungen¶
Die Variablen sind kategorial (nominal- oder ordinalskaliert)
Datensatzgröße
- Die Stichprobe ist > 50.
- Ist dies nicht der Fall, so wird bei einer Stichprobe kleiner als 20 der exakte Test nach Fisher verwendet
- bei einer Stichprobengröße zwischen 20 und 50 die Korrektur nach Yates.
Die erwarteten Zellhäufigkeiten sind > 5. Ist dies nicht der Fall, so wird der exakte Test nach Fisher verwendet.
Die Freiheitsgrade des Chi-Quadrat-Tests sind größer als 1. Ist dies nicht der Fall, so wird die Korrektur nach Yates verwendet.
import - Befehle¶
import pandas as pd # zum Einlesen und Verarbeiten von Daten
import matplotlib.pyplot as plt # (falls du grafisch darstellen möchtest)
from scipy.stats import chi2_contingency, fisher_exact # Chi-Quadrat-Test
import numpy as np # für mathematische Operationen
import plotly.graph_objects as go # Sankey
Datensatz¶
chi = pd.read_excel("chi.xlsx")
chi.head(5)
ID | vorher | nachher | |
---|---|---|---|
0 | 1 | hoch | hoch |
1 | 2 | hoch | hoch |
2 | 3 | hoch | hoch |
3 | 4 | hoch | hoch |
4 | 5 | hoch | hoch |
Balkendiagramm¶
# Kreuztabelle erzeugen (entspricht: counts <- table(vorher, nachher))
counts = pd.crosstab(chi["vorher"], chi["nachher"])
# Farben für Balken
colors = ["deepskyblue", "tomato"]
# Balkendiagramm gruppiert (stacked=False → gruppiert)
counts.plot(kind="barh",
color=colors,
figsize=(8, 5),
width=0.7,
legend=True)
# Titel und Achsen
plt.title("Balkendiagramm zur Studierbereitschaft\n(Nachher)", fontsize=14)
plt.xlabel("Studierbereitschaft vorher", fontsize=12)
plt.ylabel("Anzahl Personen", fontsize=12)
# Legende
plt.legend(title="nachher", loc="upper right")
plt.tight_layout()
plt.show()
Sankey Diagram¶
Dieses Sankey Diagramme bietet sich an bei "vorher" - "nachher" - Darstellungen.
#import plotly.graph_objects as go
# 1. Definiere Knoten und Links
labels = ["hoch_v", "niedrig_v", "hoch_n", "niedrig_n"]
# Links definieren: Quellindex, Zielindex, Werte
sources = [0, 0, 1, 1] # hoch_v, hoch_v, niedrig_v, niedrig_v
targets = [2, 3, 2, 3] # hoch_n, niedrig_n, hoch_n, niedrig_n
values = [6, 9, 25, 5]
# 2. Sankey-Diagramm erzeugen
fig = go.Figure(data=[go.Sankey(
node=dict(
pad=15,
thickness=30,
line=dict(color="black", width=0.5),
label=labels,
color="lightblue"
),
link=dict(
source=sources,
target=targets,
value=values
))])
fig.update_layout(title_text="Sankey-Diagramm: Studierbereitschaft", font_size=13)
fig.show()
Kreuztabelle und beobachteten Werte¶
# Kreuztabelle erstellen (beobachtete Werte)
counts = pd.crosstab(chi["vorher"], chi["nachher"])
print("Beobachtete Werte:\n")
print(counts)
Beobachtete Werte: nachher hoch niedrig vorher hoch 6 9 niedrig 25 5
# Chi-Quadrat-Test ohne Yates-Korrektur
chi2, p, dof, expected = chi2_contingency(counts, correction=False)
Die Tabelle wurde angelegt.
Erwarteten Werte¶
print("\nErwartete Werte (gerundet):\n")
print(pd.DataFrame(np.round(expected, 2),
index=counts.index,
columns=counts.columns))
Erwartete Werte (gerundet): nachher hoch niedrig vorher hoch 10.33 4.67 niedrig 20.67 9.33
Die beobachteten und die erwarteten Werte wurden verglichen. Es zeigen sich für das Beispiel einen Unterschiede. Ob es jedoch signifikant sind, wird mittels Chi-Quadrat-Test geprüft.
Ergebnis zum $\chi^2$ und Prüfung der Signifikanz¶
Berechnung der Freiheitsgrade¶
$$df= (k_1 -1)\cdot (k_2 -1)$$ mit
$k_1$ = die Faktorstufen der ersten Variable
$k_2$ = die Faktorstufen der zweiten Variable
$$df= (2 -1)\cdot (2 -1) = 1$$
Fall | Fisher | Yates |
---|---|---|
Fall 1 | - | - |
Fall 2 | - | + |
Fall 3 | + | - |
Fall 4 | + | + |
Fall 1¶
$$\chi^2 = \sum^I_{i=1}\sum^J_{j=1}\frac{(f_{ij}-f^{'}_{ij})^2}{f^{'}_{ij}} =\frac{(6-10.33)^2}{10.33}+ \frac{(25-20.67)^2}{20.67}+\frac{(9-4.67)^2}{4.67}+\frac{(5-9.33)^2}{9.33}=8.7$$
round(((6-10.33)**2/10.33)+((25-20.67)**2/20.67)+((9-4.67)**2/4.67)+((5-9.33)**2/9.33), 1)
8.7
keine Anpassung erforderlich
ch = chi2_contingency(counts, correction = False) # correct = F ohne Anpassungen - die "normale" Formel
ch
Chi2ContingencyResult(statistic=np.float64(8.761520737327189), pvalue=np.float64(0.0030765241259335468), dof=1, expected_freq=array([[10.33333333, 4.66666667], [20.66666667, 9.33333333]]))
Bericht:(Chi-Quadrat(1) = 8.7615, p = .003077)
Fall 2¶
**Anpassung: Korrektur nach Yates **
$$\chi^2 = \sum^I_{i=1}\sum^J_{j=1}\frac{(\Bigl| f_{ij}-f^{'}_{ij}\Bigl| -0.5)^2}{f^{'}_{ij}} = \\ \frac{(\Bigl| (6-10.33)\Bigl| -0.5)^2}{10.33} +\frac{(\Bigl| (25-20.67)\Bigl| -0.5)^2}{20.67} + \\ \frac{(\Bigl| ((9-4.67)\Bigl| -0.5)^2}{4.67} +\frac{(\Bigl| (5-9.33)\Bigl| -0.5)^2}{9.33} = 6.8$$
round(
(((abs(6-10.33))-0.5)**2/10.33)+
(((abs(25-20.67))-0.5)**2/20.67)+
(((abs(9-4.67))-0.5)**2/4.67)+
(((abs(5-9.33))-0.5)**2/9.33)
,2)
6.84
ch = chi2_contingency(counts, correction = True) # Die Anpassung nach Yates - correct = TRUE - Die Formel wird um -0.5 erweitert
ch
Chi2ContingencyResult(statistic=np.float64(6.8562788018433185), pvalue=np.float64(0.008833031444231193), dof=1, expected_freq=array([[10.33333333, 4.66666667], [20.66666667, 9.33333333]]))
Bericht:(Chi-Quadrat(1) = 6.8563, p = .008833)
Fall 3¶
**Anpassung: Fisher's Exact Test **
ch = chi2_contingency(counts, correction = False)
print(ch)
# Fisher-Test (nur für 2x2 Tabellen)
oddsratio, p_fisher = fisher_exact(counts)
print("\nFisher-Test:")
print(f"Odds Ratio: {oddsratio:.4f}")
print(f"p-Wert: {p_fisher:.4f}")
Chi2ContingencyResult(statistic=np.float64(8.761520737327189), pvalue=np.float64(0.0030765241259335468), dof=1, expected_freq=array([[10.33333333, 4.66666667], [20.66666667, 9.33333333]])) Fisher-Test: Odds Ratio: 0.1333 p-Wert: 0.0057
Bericht:(Chi-Quadrat(1) = 8.7615, p = .005673)
In dieser Übung ist es notwending nach Fisher und nach Yates zu korregieren. Daher wird folgender Code verwendet.
Fall 4¶
**Anpassung: Fisher's Exact Test & Anpassung nach Yates **
3) bei einer Stichprobengröße zwischen 20 und 50 die Korrektur nach Yates.
*Die erwarteten Zellhäufigkeiten sind > 5. Ist dies nicht der Fall, so wird der exakte Test nach Fisher verwendet.**
Die Freiheitsgrade des Chi-Quadrat-Tests sind größer als 1. Ist dies nicht der Fall, so wird die Korrektur nach Yates verwendet.
ch = chi2_contingency(counts, correction = True)
print(ch)
# Fisher-Test (nur für 2x2 Tabellen)
oddsratio, p_fisher = fisher_exact(counts)
print("\nFisher-Test:")
print(f"Odds Ratio: {oddsratio:.4f}")
print(f"p-Wert: {p_fisher:.4f}")
Chi2ContingencyResult(statistic=np.float64(6.8562788018433185), pvalue=np.float64(0.008833031444231193), dof=1, expected_freq=array([[10.33333333, 4.66666667], [20.66666667, 9.33333333]])) Fisher-Test: Odds Ratio: 0.1333 p-Wert: 0.0057
Hinweise: Da in dieser Übungsaufgabe der exakte Test nach Fisher verwendet werden muss, wird nicht folgender p-value = 0.008833 zitiert, sondern Fisher mit einem p-value von 0.005673.
Der Test bestätigt, dass ein Zusammenhang zwischen Studierbereitschaft vor dem Auslandsjahr und die Studierbereitschaft nach dem Auslandsjahr besteht (Chi-Quadrat(1) = 6.8563, p = .005673).
Alternative Darstellung mit gmodels¶
import researchpy as rp
# Kreuztabelle + Statistik (wie CrossTable in R)
table, results = rp.crosstab(chi['vorher'], chi['nachher'], prop='col', test='chi-square')
print("Kreuztabelle:")
print(table)
print("\nChi²-Test-Ergebnisse:")
print(results)
Kreuztabelle: nachher nachher hoch niedrig All vorher hoch 19.35 64.29 33.33 niedrig 80.65 35.71 66.67 All 100.00 100.00 100.00 Chi²-Test-Ergebnisse: Chi-square test results 0 Pearson Chi-square ( 1.0) = 8.7615 1 p-value = 0.0031 2 Cramer's phi = 0.4412
/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/researchpy/crosstab.py:146: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value 'Pearson Chi-square ( 1.0) = ' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
Cramers V¶
$$ Cramers\phantom{.}V = \sqrt{\frac{\chi^2}{n\cdot min[k_1-1,k_2-1]}} $$
** Die Zahl $2$ steht für $2\times2$ Design.**
$$ Cramers\phantom{.}V = \sqrt{\frac{\chi^2}{n\cdot (2-1)}} $$
$$ Cramers\phantom{.}V = \sqrt{\frac{6.86}{45\cdot (2-1)}} $$
# Anzahl Zeilen
anzahl = len(chi)
print(f"Der Datensatz hat {anzahl} Zeilen.")
Der Datensatz hat 45 Zeilen.
# Chi²-Test ohne Korrektur
chi2, p, dof, expected = chi2_contingency(counts, correction=True)
print(f"Das Chi-Quadrat liegt bei {chi2:.2f}.")
Das Chi-Quadrat liegt bei 6.86.
# Cramérs V berechnen
cramersV = np.sqrt(chi2 / (anzahl * (min(counts.shape) - 1)))
print(f"Die Effektstärke liegt bei {cramersV:.2f}.")
Die Effektstärke liegt bei 0.39.
Cramer s V ist immer positiv -> keine Aussage über die Richtung des Zusammenhangs
$$ \begin{align} \text{Schwacher Effekt: } 0.1 &< ||Cramers V|| \leq 0.3 \\ \text{Schwacher bis mittlerer Effekt: }0.3 &< ||Cramers V|| \leq 0.4 \\ \text{Mittlerer Effekt: } 0.4 &< ||Cramers V|| < 0.5 \\ \text{Mittlerer bis starker Effekt: }0.5 &= ||Cramers V|| \\ \text{Starker Effekt: } 0.5 &< ||Cramers V|| \end{align}$$
Es zeigt sich für unsere Auswertung, dass ein mittlerer Zusammenhang besteht.
Aussage¶
Die Studierbereitschaft vor dem Auslandsjahr und die Studierbereitschaft nach dem Auslandsjahr stehen in einem Zusammenhang (Chi-Quadrat(1) = 6.8563, p = .005673, n = 45). Der Zusammenhang ist mittelstark (Cramers V = .4). Damit kann die H0 verworfen werden.
Alternative¶
Es kann davon ausgegangen werden, dass sich die erwarteten und die beobachteten Häufigkeiten signifikant unterscheiden (Chi-Quadrat(1) = 6.8563, p = .005673, n = 45).Der Zusammenhang ist mittelstark (Cramers V = .4). Damit kann die H0 verworfen werden.