Извадка и популация
Накратко: Извадката е част от популацията, а средната ѝ скача от извадка на извадка; шумът намалява с корен от размера: 4 пъти повече данни дават наполовина по-малко шум.
Проблем
Две извадки, две средни
Управителят иска да знае колко е средната поръчка. Не му се чака отчетът за годината: взима 30 поръчки от системата и смята 12,11 €. Колежката му взима други 30 и получава 10,33 €.
Кой е прав? Нито един от двамата не е сгрешил в сметката. Различни са само поръчките, които са взели. Колко може да се вярва на средна от 30 поръчки? А от 3 000?
Идеята
Популация и извадка
Всичко, за което питаш, се казва популация (population): тук това са всички поръчки за годината без отказаните. Частта, която си погледнал, е извадка (sample).
Обикновено популацията не я виждаш цялата: всички клиенти, всички бъдещи поръчки. Тук я имаш и затова можеш да провериш колко греши една извадка. Истината е:
Средната на всички 10 459 поръчки е 10,63 €. Всяка извадка ще я сравняваме с това число.
Идеята
Случайна извадка с NumPy
np.random.default_rng(42) създава генератор на случайни числа. 42 е seed: началото, от което тръгва. С едно и също seed всяко пускане дава едни и същи числа. Така примерите тук показват винаги същото, а ти можеш да провериш всеки резултат.
rng.choice(values, size=30, replace=False) взима 30 различни поръчки на случаен принцип. Три извадки от всеки размер:
Средните от 30 поръчки са 11,33 €, 12,11 € и 10,33 €: това са числата на управителя и колежката. При 300 поръчки са от 10,07 € до 11,42 €. При 3 000 са от 10,65 € до 11,02 €: по-близо една до друга и до истината 10,63 €.
Идеята
Хиляда извадки
Три извадки са малко, за да видиш колко скача средната. Нека са по 1 000 от всеки размер. rng.choice(values, size=(1000, n)) дава таблица 1 000 × n: всеки ред е една извадка. mean(axis=1) дава средната на всеки ред: 1 000 средни.
Всяка хистограма е 1 000 средни, а черната линия е истината. При 30 поръчки 90% от средните са между 7,99 € и 13,85 €: извадка от 30 може да покаже почти всичко. При 300 са между 9,80 € и 11,50 €, а при 3 000 между 10,35 € и 10,91 €.
sharex=True дава на трите графики една и съща хоризонтална ос, за да се сравняват. Без него всяка графика щеше да се разтегне по своите средни и трите щяха да изглеждат еднакво широки.
По-точно, за любопитните
Тук извадките са с връщане (по подразбиране replace=True): една поръчка може да се падне два пъти в една извадка. Това позволява 1 000 извадки наведнъж, в една таблица. При 30 или 3 000 от 10 459 поръчки разликата с извадка без връщане е малка.
Поръчките имат дълга опашка надясно, а хистограмите на средните са симетрични, като камбана. Средната на достатъчно много поръчки се държи така почти каквито и да са самите поръчки: колкото по-дълга е опашката, толкова повече поръчки трябват за камбаната. Това се казва централна гранична теорема.
Идеята
Законът за големите числа
Какво става, ако трупаш поръчки една по една и след всяка смяташ средната до момента? np.cumsum дава сбора до всяка позиция. Делиш го на броя до нея (np.arange(1, 3001)) и имаш средната след 1, 2, … 3 000 поръчки:
След 10 поръчки средната е 11,29 €, след 100 е 9,82 €, след 1 000 е 10,96 €, а след 3 000 е 10,65 €. В началото скача силно, после се успокоява около истината. Това е законът за големите числа: колкото по-голяма е случайната извадка, толкова по-близо е средната ѝ до средната на популацията.
set_xscale('log') слага по хоризонталата 1, 10, 100, 1 000 на равни разстояния. Така и началото, където става всичко, и края се виждат.
Идеята
Шумът намалява с корена на n
С колко по-точна става средната, когато вземеш повече поръчки? Сравни 100, 400 и 1 600: всеки размер е 4 пъти по-голям от предишния.
Шумът е std на 1 000-те средни: 0,93 € при 100 поръчки, 0,447 € при 400 и 0,238 € при 1 600. Всеки път 4 пъти повече поръчки дават около два пъти по-малко шум. Шумът намалява с корена на размера, не със самия размер.
Затова има кратък път без симулация: стандартното отклонение на поръчките, разделено на корен от n. Това се казва стандартна грешка (standard error): 9,43 / √100 ≈ 0,94 €. Формулата и симулацията дават почти едно и също (0,472 € срещу 0,447 € при 400; разликата е шумът на самата симулация).
Цената е висока: за два пъти по-точна средна ти трябват 4 пъти повече данни, а за 10 пъти по-точна 100 пъти повече.
Пробвай
Шумът на 400 поръчки
Колко е шумът на средната от 400 поръчки? Направи 1 000 извадки по 400 поръчки и запиши в noise стандартното отклонение на техните средни.
Решение
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
items = pd.read_csv('year_items.csv')
items['revenue'] = items['quantity'] * items['unit_price']
orders['value'] = orders['id'].map(items.groupby('order_id')['revenue'].sum())
# Отказаните поръчки не са оборот: без тях.
values = orders[orders['status'] != 'cancelled']['value'].to_numpy()
true_mean = values.mean()
rng = np.random.default_rng(1)
means = rng.choice(values, size=(1000, 400)).mean(axis=1)
noise = means.std()
print(round(noise, 3))rng.choice(values, size=(1000, 400)).mean(axis=1) дава 1 000 средни, а тяхното std е около 0,45 €. Формулата казва 9,43 / √400 = 9,43 / 20 ≈ 0,47 €. std на една извадка (около 9,4 €) е разсейването на самите поръчки, а не на средната. А 9,43 / 400 ≈ 0,02 € е деление на n вместо на √n.
Идеята
„Декември падна десет пъти“
В първия урок на курса оборотът на малкия магазин през декември беше 22,70 €, а през октомври 255 €. Таблицата има 53 поръчки без отказаните, за 14 месеца: около 4 на месец. През декември са 2, през октомври 7.
Ако всички месеци бяха еднакви, каква разлика би дала само случайността? Пращаме всяка от 53-те поръчки в случаен месец и смятаме оборота на всеки месец. 1 000 пъти:
rng.integers(0, 14, ...) дава на всяка поръчка номер на месец от 0 до 13. np.where(month == m, values, 0) оставя стойността само на поръчките от месец m, а sum(axis=1) ги събира за всяка измислена година.
В 85,6% от измислените години най-силният месец е поне 10 пъти над най-слабия. А в тях месеците по замисъл са еднакви. Десеторният спад не е знак за нищо: при 4 поръчки на месец той е обичайният шум.
В годишните данни месецът има средно около 870 поръчки и шумът е много по-малък. Затова декември там е наистина най-силен. Спадът през септември е друг въпрос: дали е шум и защо е, ще разберем в проекта.
Упражнение
Колко поръчки стигат?
Управителят иска средната поръчка с точност ±0,50 € в 95 от 100 случая. За извадки от 100, 300, 1 000, 2 000 и 3 000 поръчки направи по 1 000 извадки и запиши в close (речник: размер → дял) колко от средните са на най-много 0,50 € от истинската. В enough запиши най-малкия размер, който стига.
Решение
import numpy as np
import pandas as pd
orders = pd.read_csv('year_orders.csv')
items = pd.read_csv('year_items.csv')
items['revenue'] = items['quantity'] * items['unit_price']
orders['value'] = orders['id'].map(items.groupby('order_id')['revenue'].sum())
# Отказаните поръчки не са оборот: без тях.
values = orders[orders['status'] != 'cancelled']['value'].to_numpy()
true_mean = values.mean()
rng = np.random.default_rng(3)
close = {}
for n in [100, 300, 1000, 2000, 3000]:
means = rng.choice(values, size=(1000, n)).mean(axis=1)
close[n] = float((np.abs(means - true_mean) <= 0.5).mean())
print(close)
enough = min(n for n in close if close[n] >= 0.95)
print(enough)С rng = np.random.default_rng(3) делът е 41,5% при 100 поръчки, 63,9% при 300, 92,7% при 1 000, 97,6% при 2 000 и 99,5% при 3 000. 1 000 поръчки не стигат за 95%, 2 000 стигат. Със стандартната грешка: при 2 000 поръчки тя е 9,43 / √2 000 ≈ 0,21 €, а 0,50 € са около 2,4 такива. Ако сравниш средната на всичките 1 000 средни с истината, тя винаги е близо: това не казва колко греши една извадка.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Групи: groupby · Първата графика · Разпределения · Описание на данните
- Продължава в: Доверителен интервал · Проверка на хипотеза · A/B тест · Кръстосана проверка (cross-validation)
- Задачи по темата: Статистика за решения