Zum Inhalt
wannacode

Eine Hypothese testen

Kurz gesagt: Ein Hypothesentest fragt, ob ein Unterschied Zufall sein könnte: Die Nullhypothese sagt „kein Unterschied“, und der p-Wert ist, wie oft der Zufall einen mindestens so großen Unterschied liefert.

Problem

„Ist der Freitag wirklich stärker?“

Der Chef will freitags eine Person mehr an das Packen stellen und sonntags eine abziehen. Vorher fragt er: Ist der Freitag wirklich stärker, oder ist es dieses Jahr nur so gekommen? So viele Bestellungen kommen im Mittel pro Tag an, nach Wochentag (0 ist Montag, 6 ist Sonntag):

PythonDaten: die Tabellen des Shops

Wir zählen alle Bestellungen, auch die stornierten: Die Frage ist, wie viele ankommen, und eine stornierte Bestellung wird ebenfalls empfangen und bearbeitet. An einem Freitag kommen im Mittel 36,35 Bestellungen an, an einem Sonntag 24,62. Das Jahr hat 52 Freitage und ebenso 52 Sonntage. Jeder Tag ist ein bisschen anders: Ein Freitag bringt 22 Bestellungen, ein anderer 68. Ist ein Abstand von 11,73 Bestellungen echt, oder ist er Rauschen wie in der Lektion über Stichproben?

Die Idee

Wenn der Tag keine Rolle spielte

Die Frage „Ist der Freitag stärker als der Sonntag?“ ist eine Hypothese. Um sie zu prüfen, gehst du von der langweiligen Erklärung aus: Der Tag spielt keine Rolle, und der Abstand ist Zufall. Das ist die Nullhypothese.

Stimmt die Nullhypothese, bedeuten die Labels „Freitag“ und „Sonntag“ nichts. Du kannst sie mischen: Leg die 104 Tage auf einen Haufen, misch sie und sag, die ersten 52 seien „Freitage“ und die anderen 52 „Sonntage“. Der Abstand zwischen den beiden Hälften ist der Abstand, den der Zufall allein liefert:

PythonDaten: die Tabellen des Shops

Der echte Abstand ist 11,73 Bestellungen. Drei Mischungen geben 0,50, 1,23 und 1,46. np.concatenate klebt die beiden Arrays zu einem zusammen, und rng.permutation gibt eine gemischte Kopie zurück.

Die Idee

10.000 Mischungen und der p-Wert

Drei Mischungen sind zu wenig. Du machst 10.000 auf einmal: np.tile wiederholt die 104 Tage in 10.000 Zeilen, und rng.permuted(..., axis=1) mischt jede Zeile für sich. Dann liefert eine einzige Rechnung den Abstand für jede Zeile:

PythonDaten: die Tabellen des Shops

Der größte Abstand aus 10.000 Mischungen ist 7,50 Bestellungen. Der echte ist 11,73. Der Anteil der Mischungen mit einem mindestens so großen Abstand ist der p-Wert: Hier ist er 0, also unter 1 zu 10.000. Spielte der Tag keine Rolle, käme ein solcher Abstand fast nie vor. Die Schlussfolgerung: Der Freitag ist wirklich stärker.

Diese Methode heißt Permutationstest. np.abs steht da, weil die Frage „gibt es einen Unterschied“ lautet, ohne vorher zu sagen, in welche Richtung. Die übliche Schwelle ist 0,05: Liegt p darunter, sagst du, der Unterschied ist statistisch signifikant.

Probier es aus

Montag und Samstag

1. Der Permutationstest für Freitag gegen Sonntag ergibt p = 0 bei 10.000 Mischungen. Was bedeutet das?

Der Abstand zwischen Montag und Samstag ist kleiner. Ist er Zufall? Speichere in gap die Differenz der durchschnittlichen Bestellungen pro Tag (Montag minus Samstag), in gaps die Abstände aus 10.000 Mischungen und in p den p-Wert.

PythonDaten: die Tabellen des Shops

Die Idee

Wenn es keinen Unterschied gibt

Am Sonntag gibt es weniger Bestellungen. Sind auch die Bestellungen selbst kleiner? Hier werden 10.459 Bestellungen ohne die stornierten verglichen, nicht Tage, deshalb würde eine Zahlentabelle von 2.000 × 10.459 etwa 170 MB brauchen. Eine Schleife mit 2.000 Mischungen der Maske braucht unter einer Sekunde:

PythonDaten: die Tabellen des Shops

Es gibt 1.204 Sonntags-Bestellungen mit einem Durchschnitt von 10,83 €, und die anderen liegen im Schnitt bei 10,60 €. Der Abstand ist 0,23 €, und p = 0,425: In 42,5 % der Mischungen ist der Abstand mindestens so groß. Das ist gewöhnliches Rauschen.

Die ehrliche Schlussfolgerung lautet „es gibt keinen Beleg dafür, dass die Sonntags-Bestellung anders ist“. Sie lautet nicht „wir haben bewiesen, dass sie gleich sind“: Es kann einen kleinen Unterschied geben, nur zeigen ihn diese Daten nicht. Am Sonntag bestellen die Leute seltener, und es gibt keinen Beleg dafür, dass sie weniger bestellen.

Die Idee

Was p nicht sagt

Der p-Wert beantwortet eine enge Frage: wie überraschend die Daten sind, wenn die Nullhypothese stimmt. Er ist nicht zwei Dinge, mit denen er oft verwechselt wird:

  • Er ist nicht die Wahrscheinlichkeit, dass die Hypothese stimmt: p = 0,425 heißt nicht „mit 42,5 % Wahrscheinlichkeit gibt es keinen Unterschied“;
  • er ist nicht die Größe des Unterschieds: Ein sehr kleines p heißt „nicht Zufall“, nicht „ein großer Unterschied“.

Wie groß der Unterschied ist, sagt dir der Abstand selbst mit einem Intervall. Mit dem Bootstrap aus der vorigen Lektion, getrennt für die Freitage und die Sonntage:

PythonDaten: die Tabellen des Shops

Der Freitag hat im Mittel 11,73 Bestellungen mehr, mit einem 95-%-Intervall von 9,00 bis 14,56. Das ist das 1,48-Fache des Sonntags. Mit dieser Zahl entscheidet der Chef, wie viele Leute er einteilt, und p sagt nur, dass er nicht dem Rauschen nachjagt.

Genauer, für Neugierige

Die Schwelle von 0,05 ist eine Konvention, kein Naturgesetz. Bei p = 0,06 sind die Daten kein „fast ein Beleg“, und bei p = 0,04 sind sie nicht „sicher wahr“. Bei sehr vielen Daten gibt auch ein winziger Unterschied ein kleines p: Mit einer Million Bestellungen in jeder Gruppe und einem Abstand von 10 Cent ist der Test „signifikant“, aber daraus folgt keine Entscheidung. Schreib also immer beides auf, den Abstand und das Intervall.

Die Idee

Dasselbe mit scipy

scipy.stats hat die Tests fertig. ttest_ind (der t-Test) vergleicht die Mittelwerte zweier Gruppen mit einer Formel. permutation_test übernimmt das Mischen für dich, in Portionen (batch), damit der Speicher nicht ausgeht:

PythonDaten: die Tabellen des Shops

Für die Sonntags-Bestellung gibt der t-Test 0,426, permutation_test 0,419 und unsere Schleife 0,425. Die Antwort ist dieselbe: kein Beleg. Für Freitag gegen Sonntag gibt der t-Test 1,04 × 10⁻¹²: praktisch null, wie unser 0 von 10.000.

Genauer, für Neugierige

Der t-Test setzt voraus, dass der Mittelwert jeder Gruppe fast normalverteilt ist. Bei Hunderten Bestellungen in einer Gruppe stimmt das (zentraler Grenzwertsatz). Bei wenig Daten und einem langen Schwanz ist der Permutationstest sicherer, weil er nichts über die Verteilung voraussetzt. permutation_test gibt ein p, das sich leicht von unserem unterscheidet: Die Mischungen sind andere, und es zählt auch die Daten selbst als eine davon, (Anzahl + 1) / (Mischungen + 1).

Übung

Dezember und Freitag

Im Dezember verkaufen sich Geschenkkarten. Ist die Dezember-Bestellung größer als die Bestellungen in den anderen Monaten, oder ist es Zufall? Speichere in gap die Differenz der durchschnittlichen Bestellung (Dezember minus die anderen Monate) und in p den p-Wert. Du kannst einen Permutationstest oder stats.ttest_ind benutzen.

PythonDaten: die Tabellen des Shops

Die Freitags-Bestellung ist etwas kleiner als die Bestellung an den anderen Tagen. Gibt es einen Beleg dafür? Mach einen Permutationstest mit 2.000 Mischungen (Seed 42): gap ist die Differenz der durchschnittlichen Bestellung (Freitag minus die anderen Tage), p ist der p-Wert, und evidence sagt, ob p unter der Schwelle von 0,05 liegt.

PythonDaten: die Tabellen des Shops

Test

Teste dich

1. Was ist die Nullhypothese, wenn du die durchschnittliche Bestellung am Sonntag mit der an den anderen Tagen vergleichst?
2. Für die Sonntags-Bestellung ist p = 0,425. Welche Schlussfolgerung ist ehrlich?
3. Warum wird p mit np.abs(gaps) >= abs(gap) berechnet und nicht mit gaps >= gap?
4. p für den Dezember ist 5,1 × 10⁻²³, und für Freitag gegen Sonntag 1,0 × 10⁻¹². Heißt das, der Dezember ist der größere Unterschied?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·