Konfidenzintervalle
Kurz gesagt: Ein Konfidenzintervall ist ein Bereich um den Wert aus einer Stichprobe, der bei 95 % in etwa 95 von 100 Stichproben den wahren Wert einfängt; der Bootstrap baut es aus Neustichproben mit Zurücklegen.
Problem
„Wie viel gibt ein Kunde pro Bestellung aus?“
Der Chef fragt, wie hoch die durchschnittliche Bestellung ist. Im echten Leben hast du selten alles: Sagen wir, du hast 200 Bestellungen, zufällig aus dem Jahr gezogen. Hier haben wir auch das ganze Jahr, 10.459 Bestellungen ohne die stornierten, und können sehen, was passiert:
Drei Stichproben mit 200 geben drei verschiedene Mittelwerte: 9,77 €, 10,74 € und 11,16 €. Aus der Lektion über Stichproben weißt du, dass der Mittelwert rauscht. Aber du hast nur eine Stichprobe. Was sagst du dem Chef: eine Zahl oder etwas mehr?
Ehrlicher ist es zu sagen: „Der Durchschnitt liegt irgendwo zwischen … und …“. Offen bleibt, wie breit dieses „irgendwo“ sein soll, aus der Stichprobe, die du hast, und sonst nichts.
Die Idee
Die Stichprobe statt des Jahres: der Bootstrap
Könntest du neue Stichproben aus dem Jahr ziehen, sähest du, wie stark der Mittelwert schwankt. Das kannst du nicht. Also benutzt du die Stichprobe als kleines Modell des Jahres: Du ziehst aus ihr 200 Bestellungen mit Zurücklegen und berechnest den Mittelwert. Das ist eine Neustichprobe (Resample). Eine Bestellung kommt doppelt vor, eine andere gar nicht, und der Mittelwert ist jedes Mal ein wenig anders.
Du machst das 10.000-mal und schaust, wo die Mittelwerte liegen. Du schneidest 2,5 % der kleinsten und 2,5 % der größten ab. Die mittleren 95 % sind das Konfidenzintervall. Die Methode heißt Bootstrap:
Die ersten 8 Bestellungen der Stichprobe reichen von 0,90 € bis 45,20 €. Die ersten drei Neustichproben geben Mittelwerte von 10,07 €, 11,07 € und 11,13 €. Der Mittelwert der Stichprobe ist 11,41 €, und das 95-%-Intervall reicht von 10,04 € bis 12,83 €. Der wahre Mittelwert des Jahres ist 10,63 €: Er liegt darin.
rng.choice(sample, size=(10_000, 200)) ist eine Tabelle mit 10.000 × 200: Jede Zeile ist eine Neustichprobe. mean(axis=1) gibt einen Mittelwert pro Zeile. Eine Schleife ist nicht nötig.
Sieh es dir an
Wie aus einer Stichprobe ein Intervall entsteht
Derselbe Code, langsam: Kacheln aus der Stichprobe werden in eine Neustichprobe kopiert, ihr Mittelwert fällt auf die Achse, und 10.000 solche Mittelwerte ergeben einen Haufen.
import numpy as npimport pandas as pd
orders = pd.read_csv('year_orders.csv')items = pd.read_csv('year_items.csv')cancelled = orders.loc[orders['status'] == 'cancelled', 'id']items = items[~items['order_id'].isin(cancelled)]items['revenue'] = items['quantity'] * items['unit_price']totals = items.groupby('order_id')['revenue'].sum()
rng = np.random.default_rng(42)sample = rng.choice(totals.to_numpy(), size=200, replace=False)print(sample[:8])boots = rng.choice(sample, size=(10_000, 200)).mean(axis=1)print(boots[:3].round(2))low, high = np.quantile(boots, [0.025, 0.975])print(round(sample.mean(), 2), round(low, 2), round(high, 2))print(round(totals.mean(), 2))Schritt für Schritt, in Worten
- totals ist der Wert jeder Bestellung des Jahres. Im echten Leben siehst du nicht alles: Du hast nur eine Stichprobe.
- sample ist eine Stichprobe von 200 Bestellungen. Oben stehen die ersten 8, in Euro: 3,6, 0,9, 2,1, 17, 45,2, 13,2, 3,4 und 2.
- Eine Neustichprobe: 200 Züge aus sample mit Zurücklegen. Eine Bestellung kommt doppelt vor, eine andere gar nicht.
- Der Mittelwert der Neustichprobe fällt als Punkt auf die Achse. Die ersten drei sind 10,07 €, 11,07 € und 11,13 €.
- So geht es 10.000-mal. Die Punkte häufen sich um den Mittelwert der Stichprobe, 11,41 €.
- Links werden 2,5 % und rechts 2,5 % abgeschnitten. Die mittleren 95 % sind das Intervall: von 10,04 € bis 12,83 €.
- Der wahre Mittelwert des Jahres ist 10,63 €, und er liegt darin. Im echten Leben kennst du ihn nicht: Das Intervall sagt, wie weit er danebenliegen kann.
Der Haufen in der Szene ist eine Skizze: Die Zahlen in den Beschriftungen sind echt, von der Stichprobe bis zu den Grenzen des Intervalls. Hier sind die echten 10.000 Mittelwerte mit matplotlib, mit den beiden Grenzen (blaue Linien) und dem wahren Mittelwert (die orange gestrichelte):
Probier es aus
Ohne Zurücklegen?
Der Median der Bestellungen ist gegenüber den großen Bestellungen robuster. Bilde ein 95-%-Intervall für den Median mit derselben Stichprobe von 200: Speichere die Mediane von 10.000 Neustichproben in meds und die Grenzen des Intervalls in low und high.
Lösung
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
items = pd.read_csv('year_items.csv')
cancelled = orders.loc[orders['status'] == 'cancelled', 'id']
items = items[~items['order_id'].isin(cancelled)]
items['revenue'] = items['quantity'] * items['unit_price']
totals = items.groupby('order_id')['revenue'].sum()
rng = np.random.default_rng(42)
sample = rng.choice(totals.to_numpy(), size=200, replace=False)
meds = np.median(rng.choice(sample, size=(10_000, 200)), axis=1)
low, high = np.quantile(meds, [0.025, 0.975])
print(np.median(sample), low, high)meds = np.median(rng.choice(sample, size=(10_000, 200)), axis=1) gibt einen Median pro Neustichprobe, und np.quantile(meds, [0.025, 0.975]) gibt das Intervall: von 6,25 € bis 9,45 €. Der Median der Stichprobe ist 7,95 €, der des Jahres 7,70 €, aus der Lektion über das Beschreiben der Daten: Er liegt darin. Die Quantile der Stichprobe selbst (1,20 € und 36,72 €) beantworten eine andere Frage: zwischen welchen Werten 95 % der Bestellungen liegen. Für das Intervall eines Medians brauchst du keine Formel: Der Bootstrap berechnet jede Zahl, sobald du mean gegen median tauschst.
Die Idee
Was 95 % bedeuten
Der wahre Mittelwert des Jahres ist eine Zahl: 10,63 €. Das Intervall aus einer Stichprobe fängt sie entweder ein oder nicht. 95 % ist ein Versprechen der Methode: Wenn du viele Stichproben ziehst und für jede ein Intervall baust, fangen etwa 95 von 100 Intervallen die Wahrheit ein. Das heißt Konfidenzniveau.
Hier haben wir das ganze Jahr und können das Versprechen prüfen. 100 Stichproben mit je 200, für jede ein Bootstrap mit 1.000 Neustichproben:
93 von 100 Intervallen fangen 10,63 € ein. Das liegt nah an 95: Die 100 Stichproben sind selbst zufällig, und die nächsten 100 geben etwas leicht anderes. Etwa 5 von 100 ehrlichen Intervallen verfehlen die Wahrheit, und es gibt keinen Weg zu wissen, welche.
Genauer, für Neugierige
Es ist verlockend zu sagen: „Mit einer Wahrscheinlichkeit von 95 % liegt der wahre Mittelwert zwischen 10,04 € und 12,83 €.“ Streng genommen stimmt das nicht: Der wahre Mittelwert ist nicht zufällig, und das Intervall aus deiner Stichprobe enthält ihn entweder oder nicht. Zufällig ist die Stichprobe. 95 % beziehen sich also auf die Methode, nicht auf eine bestimmte Zahl. Schreib in einem Bericht „95-%-Konfidenzintervall: 10,04 €–12,83 €“.
Der Bootstrap funktioniert, wenn die Stichprobe zufällig ist. Stammen die 200 Bestellungen aus einem einzigen Dezember, gilt das Intervall für den Dezember, egal wie viele Neustichproben du machst: Neustichproben reparieren keine schiefe Stichprobe.
Die Idee
Die Formel als Abkürzung
Für einen Mittelwert gibt es eine Abkürzung ohne 10.000 Neustichproben. Das Rauschen des Mittelwerts ist der Standardfehler: std / √n. Bei einer Normalverteilung liegen die mittleren 95 % innerhalb von 1,96 Standardfehlern um die Mitte. Das Intervall ist also der Mittelwert ± 1,96 × std / √n:
Der Standardfehler ist 0,72 €, und das Intervall reicht von 10,00 € bis 12,81 €. Der Bootstrap gab 10,04 €–12,83 €: fast dasselbe. Die zweite Zeile prüft das Versprechen der Formel: Von 1.000 Stichproben mit je 200 fangen 948 Intervalle die Wahrheit ein. Nah an 950.
std(ddof=1) teilt durch n − 1 statt durch n, wie std() in pandas. Bei 200 Bestellungen steckt der Unterschied in der dritten Stelle.
Genauer, für Neugierige
Die Zahl 1,96 kommt aus der Normalverteilung: 95 % der Fläche liegen zwischen −1,96 und 1,96 Standardabweichungen. Der Mittelwert von 200 Bestellungen ist nah an normal, selbst wenn die Bestellungen selbst einen langen Schwanz haben (der zentrale Grenzwertsatz aus der Lektion über Stichproben). Bei kleinen Stichproben, unter 30, oder bei einem sehr langen Schwanz liegt die Formel weiter daneben, und der Bootstrap ist ehrlicher.
Die Idee
Ein Intervall für einen Anteil
Welcher Teil der Bestellungen ist storniert? Ein Anteil ist ein Mittelwert aus Nullen und Einsen: True ist 1, False ist 0, und mean() gibt den Anteil. Also funktionieren der Bootstrap und die Formel auch hier. Die Formel für einen Anteil ist p ± 1,96 × √(p(1 − p) / n):
In einer Stichprobe von 500 Bestellungen sind 5,8 % storniert. Der Bootstrap gibt von 3,8 bis 8,0 %, die Formel von 3,8 bis 7,8 %. Der wahre Anteil für das Jahr ist 5,9 %. Aus 500 Bestellungen kennst du den Anteil auf etwa ± 2 Punkte genau: „5,8 %“ ohne Intervall klingt genauer, als es ist.
Die Idee
Eine kleine Stichprobe, ein breites Intervall
Je weniger Bestellungen, desto stärker rauscht der Mittelwert und desto breiter ist das Intervall:
50 Bestellungen geben ein Intervall von 4,73 € Breite, 200 Bestellungen 2,69 € und 800 Bestellungen 1,35 €. 4-mal so viele Daten geben ein etwa halb so breites Intervall, weil der Standardfehler mit der Wurzel aus n fällt. Genauigkeit ist teuer: Die Breite noch einmal zu halbieren braucht wieder 4-mal so viele Bestellungen.
Übung
Die Antwort für den Chef
Eine neue Stichprobe von 400 Bestellungen (Seed 2026). Bilde ein 95-%-Intervall für die durchschnittliche Bestellung auf zwei Wegen: mit einem Bootstrap aus 10.000 Neustichproben (boot_low, boot_high) und mit der Formel (se ist der Standardfehler, f_low und f_high sind die Grenzen).
Lösung
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
items = pd.read_csv('year_items.csv')
cancelled = orders.loc[orders['status'] == 'cancelled', 'id']
items = items[~items['order_id'].isin(cancelled)]
items['revenue'] = items['quantity'] * items['unit_price']
totals = items.groupby('order_id')['revenue'].sum()
rng = np.random.default_rng(2026)
sample = rng.choice(totals.to_numpy(), size=400, replace=False)
boots = rng.choice(sample, size=(10_000, 400)).mean(axis=1)
boot_low, boot_high = np.quantile(boots, [0.025, 0.975])
se = sample.std(ddof=1) / np.sqrt(len(sample))
f_low = sample.mean() - 1.96 * se
f_high = sample.mean() + 1.96 * se
print(round(sample.mean(), 2))
print(round(boot_low, 2), round(boot_high, 2))
print(round(f_low, 2), round(f_high, 2))Der Mittelwert der Stichprobe ist 10,80 €. Der Bootstrap gibt von 9,79 € bis 11,90 €, die Formel von 9,74 € bis 11,85 €. Die Antwort für den Chef lautet „die durchschnittliche Bestellung liegt bei etwa 10,80 €, mit einem 95-%-Konfidenzintervall von 9,79 € bis 11,90 €“. Mit se = sample.std(ddof=1) ohne die Wurzel aus n wäre das Intervall ± 21,10 €: So sehr unterscheiden sich die Bestellungen, nicht wie stark ihr Mittelwert rauscht.
Der Chef denkt über kostenlose Lieferung ab 20 € nach. Welcher Teil der Bestellungen liegt über 20 €? Speichere aus einer Stichprobe von 300 Bestellungen (Seed 7) den Anteil in p und sein 95-%-Intervall in low und high.
Lösung
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
items = pd.read_csv('year_items.csv')
cancelled = orders.loc[orders['status'] == 'cancelled', 'id']
items = items[~items['order_id'].isin(cancelled)]
items['revenue'] = items['quantity'] * items['unit_price']
totals = items.groupby('order_id')['revenue'].sum()
rng = np.random.default_rng(7)
sample = rng.choice(totals.to_numpy(), size=300, replace=False)
big = sample > 20
p = big.mean()
se = np.sqrt(p * (1 - p) / len(sample))
low, high = p - 1.96 * se, p + 1.96 * se
print(round(p, 3), round(low, 3), round(high, 3))
print(round((totals > 20).mean(), 3))big = sample > 20 ist eine Maske, und big.mean() ist der Anteil: 12,7 %. Der Standardfehler eines Anteils ist np.sqrt(p * (1 - p) / 300), und das Intervall reicht von 8,9 bis 16,4 %. Der wahre Anteil für das Jahr ist 13,3 %: Er liegt darin. big.sum() würde die Anzahl der Bestellungen geben, 38, nicht den Anteil.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Das erste Diagramm · Verteilungen · Die Daten beschreiben · Stichprobe und Grundgesamtheit
- Geht weiter in: Eine Hypothese testen · A/B-Test · Warum ist der Umsatz gefallen?
- Aufgaben zum Thema: Statistik für Entscheidungen