Levene-Test für gleiche Varianzen#

Der Levene-Test scipy.stats.levene testet die Nullhypothese, dass alle Eingabestichproben aus Populationen mit gleichen Varianzen stammen. Der Levene-Test ist eine Alternative zum Bartlett-Test scipy.stats.bartlett in Fällen, in denen erhebliche Abweichungen von der Normalverteilung vorliegen.

In [1] wurde der Einfluss von Vitamin C auf das Zahnwachstum von Meerschweinchen untersucht. In einer Kontrollstudie wurden 60 Probanden in Gruppen mit geringer, mittlerer und hoher Dosis eingeteilt, die täglich 0,5, 1,0 bzw. 2,0 mg Vitamin C erhielten. Nach 42 Tagen wurde das Zahnwachstum gemessen.

Die unten aufgeführten Arrays small_dose, medium_dose und large_dose erfassen die Zahnwachstumsmessungen der drei Gruppen in Mikrometern.

import numpy as np
small_dose = np.array([
    4.2, 11.5, 7.3, 5.8, 6.4, 10, 11.2, 11.2, 5.2, 7,
    15.2, 21.5, 17.6, 9.7, 14.5, 10, 8.2, 9.4, 16.5, 9.7
])
medium_dose = np.array([
    16.5, 16.5, 15.2, 17.3, 22.5, 17.3, 13.6, 14.5, 18.8, 15.5,
    19.7, 23.3, 23.6, 26.4, 20, 25.2, 25.8, 21.2, 14.5, 27.3
])
large_dose = np.array([
    23.6, 18.5, 33.9, 25.5, 26.4, 32.5, 26.7, 21.5, 23.3, 29.5,
    25.5, 26.4, 22.4, 24.5, 24.8, 30.9, 26.4, 27.3, 29.4, 23
])

Die scipy.stats.levene-Statistik ist empfindlich gegenüber Unterschieden in den Varianzen zwischen den Stichproben.

from scipy import stats
res = stats.levene(small_dose, medium_dose, large_dose)
res.statistic
np.float64(0.6457341109631506)

Der Wert der Statistik tendiert dazu, hoch zu sein, wenn es einen großen Unterschied in den Varianzen gibt.

Wir können auf Ungleichheit der Varianzen unter den Gruppen testen, indem wir den beobachteten Wert der Statistik mit der Nullverteilung vergleichen: der Verteilung von Statistikwerten, die unter der Nullhypothese abgeleitet werden, dass die Populationsvarianzen der drei Gruppen gleich sind.

Für diesen Test folgt die Nullverteilung der F-Verteilung, wie unten gezeigt.

import matplotlib.pyplot as plt
k, n = 3, 60   # number of samples, total number of observations
dist = stats.f(dfn=k-1, dfd=n-k)
val = np.linspace(0, 5, 100)
pdf = dist.pdf(val)
fig, ax = plt.subplots(figsize=(8, 5))

def plot(ax):  # we'll reuse this
    ax.plot(val, pdf, color='C0')
    ax.set_title("Levene Test Null Distribution")
    ax.set_xlabel("statistic")
    ax.set_ylabel("probability density")
    ax.set_xlim(0, 5)
    ax.set_ylim(0, 1)

plot(ax)
plt.show()
../../_images/354e79001920cc723f7d0273dd8576e15fcff56ed41dcb37353f34a96e0ae756.png

Der Vergleich wird durch den p-Wert quantifiziert: der Anteil der Werte in der Nullverteilung, die größer oder gleich dem beobachteten Wert der Statistik sind.

fig, ax = plt.subplots(figsize=(8, 5))
plot(ax)
pvalue = dist.sf(res.statistic)
annotation = (f'p-value={pvalue:.3f}\n(shaded area)')
props = dict(facecolor='black', width=1, headwidth=5, headlength=8)
_ = ax.annotate(annotation, (1.5, 0.22), (2.25, 0.3), arrowprops=props)
i = val >= res.statistic
ax.fill_between(val[i], y1=0, y2=pdf[i], color='C0')
plt.show()
../../_images/145c8de42c7dd69ca9769ffaff929a61a11cc0e77ce0b90917df7f02bf3b13be.png
res.pvalue
np.float64(0.5280694573759905)

Wenn der p-Wert „klein“ ist – das heißt, wenn die Wahrscheinlichkeit gering ist, Daten aus Verteilungen mit identischen Varianzen zu ziehen, die einen so extremen Wert der Statistik erzeugen – kann dies als Beweis gegen die Nullhypothese zugunsten der Alternative genommen werden: Die Varianzen der Gruppen sind nicht gleich. Beachten Sie, dass

  • Das Umgekehrte gilt nicht; d.h. der Test wird nicht verwendet, um Beweise für die Nullhypothese zu liefern.

  • Der Schwellenwert für Werte, die als „klein“ gelten, ist eine Wahl, die vor der Analyse der Daten getroffen werden sollte [2] und die Risiken von sowohl falsch positiven Ergebnissen (fälschliche Ablehnung der Nullhypothese) als auch falsch negativen Ergebnissen (Nichtablehnung einer falschen Nullhypothese) berücksichtigt.

  • Kleine p-Werte sind kein Beweis für einen *großen* Effekt; sie können nur einen Beweis für einen „signifikanten“ Effekt liefern, was bedeutet, dass sie unter der Nullhypothese unwahrscheinlich aufgetreten wären.

Beachten Sie, dass die F-Verteilung eine asymptotische Annäherung der Nullverteilung darstellt. Bei kleinen Stichproben kann es sinnvoller sein, einen Permutationstest durchzuführen: Unter der Nullhypothese, dass alle drei Stichproben aus derselben Population stammen, ist es für jede der Messungen gleich wahrscheinlich, dass sie in einer der drei Stichproben beobachtet wurde. Daher können wir eine randomisierte Nullverteilung bilden, indem wir die Statistik unter vielen zufällig generierten Partitionierungen der Beobachtungen in die drei Stichproben berechnen.

def statistic(*samples):
    return stats.levene(*samples).statistic
ref = stats.permutation_test(
    (small_dose, medium_dose, large_dose), statistic,
    permutation_type='independent', alternative='greater'
)
fig, ax = plt.subplots(figsize=(8, 5))
plot(ax)
bins = np.linspace(0, 5, 25)
ax.hist(
    ref.null_distribution, bins=bins, density=True, facecolor="C1"
)
ax.legend(['asymptotic approximation\n(many observations)',
           'randomized null distribution'])
plot(ax)
plt.show()
../../_images/790fd5aa693a08819c5c26d7582a99f5e7a46de110e51ccf1dba5f627dad75b8.png
ref.pvalue  # randomized test p-value
np.float64(0.4568)

Beachten Sie, dass es erhebliche Meinungsverschiedenheiten zwischen dem hier berechneten p-Wert und der asymptotischen Annäherung gibt, die von scipy.stats.levene oben zurückgegeben wird. Die statistischen Schlussfolgerungen, die rigoros aus einem Permutationstest gezogen werden können, sind begrenzt; dennoch können sie in vielen Fällen die bevorzugte Methode sein [3].

Referenzen#