Найти в Дзене
ЦифроПроф

Bootstrap

Bootstrap - техника вычисления сложных величин без применения каких-либо формул. Чтобы получить нужную величину, например, среднее, из исходного набора данных формируют подвыборки (псевдовыборки). На каждой из них и вычисляют среднее. Рассмотрим на примере Задача 1 Процедурой бутстреп создайте 10 подвыборок и для каждой найдите 0.99-квантиль. Напечатайте их на экране через перенос строки. import pandas as pd
import numpy as np
data = pd.Series([
10.7 , 9.58, 7.74, 8.3 , 11.82, 9.74, 10.18, 8.43, 8.71,
6.84, 9.26, 11.61, 11.08, 8.94, 8.44, 10.41, 9.36, 10.85,
10.41, 8.37, 8.99, 10.17, 7.78, 10.79, 10.61, 10.87, 7.43,
8.44, 9.44, 8.26, 7.98, 11.27, 11.61, 9.84, 12.47, 7.8 ,
10.54, 8.99, 7.33, 8.55, 8.06, 10.62, 10.41, 9.29, 9.98,
9.46, 9.99, 8.62, 11.34, 11.21, 15.19, 20.85, 19.15, 19.01,
15.24, 16.66, 17.62, 18.22, 17.2 , 15.76, 16.89, 15.22, 18.7 ,
14.84, 14.88, 19.41, 18.54, 17.85, 18.31, 13.68, 18.46, 13.99,
16.38, 16
Фото из открытых источников
Фото из открытых источников

Bootstrap - техника вычисления сложных величин без применения каких-либо формул. Чтобы получить нужную величину, например, среднее, из исходного набора данных формируют подвыборки (псевдовыборки). На каждой из них и вычисляют среднее. Рассмотрим на примере

Задача 1

Процедурой бутстреп создайте 10 подвыборок и для каждой найдите 0.99-квантиль. Напечатайте их на экране через перенос строки.

import pandas as pd
import numpy as np

data = pd.Series([
10.7 , 9.58, 7.74, 8.3 , 11.82, 9.74, 10.18, 8.43, 8.71,
6.84, 9.26, 11.61, 11.08, 8.94, 8.44, 10.41, 9.36, 10.85,
10.41, 8.37, 8.99, 10.17, 7.78, 10.79, 10.61, 10.87, 7.43,
8.44, 9.44, 8.26, 7.98, 11.27, 11.61, 9.84, 12.47, 7.8 ,
10.54, 8.99, 7.33, 8.55, 8.06, 10.62, 10.41, 9.29, 9.98,
9.46, 9.99, 8.62, 11.34, 11.21, 15.19, 20.85, 19.15, 19.01,
15.24, 16.66, 17.62, 18.22, 17.2 , 15.76, 16.89, 15.22, 18.7 ,
14.84, 14.88, 19.41, 18.54, 17.85, 18.31, 13.68, 18.46, 13.99,
16.38, 16.88, 17.82, 15.17, 15.16, 18.15, 15.08, 15.91, 16.82,
16.85, 18.04, 17.51, 18.44, 15.33, 16.07, 17.22, 15.9 , 18.03,
17.26, 17.6 , 16.77, 17.45, 13.73, 14.95, 15.57, 19.19, 14.39,
15.76])

state = np.random.RandomState(12345)

for i in range(10):
subsample = data.sample(frac=1, replace=True, random_state=state)
print(subsample.quantile(0.99))

Задача 2

Процедурой бутстреп найдите 90%-й доверительный интервал для 0.99-квантиля. Сохраните начало интервала в переменной lower, а конец — в upper.

import pandas as pd
import numpy as np

data = pd.Series([
10.7 , 9.58, 7.74, 8.3 , 11.82, 9.74, 10.18, 8.43, 8.71,
6.84, 9.26, 11.61, 11.08, 8.94, 8.44, 10.41, 9.36, 10.85,
10.41, 8.37, 8.99, 10.17, 7.78, 10.79, 10.61, 10.87, 7.43,
8.44, 9.44, 8.26, 7.98, 11.27, 11.61, 9.84, 12.47, 7.8 ,
10.54, 8.99, 7.33, 8.55, 8.06, 10.62, 10.41, 9.29, 9.98,
9.46, 9.99, 8.62, 11.34, 11.21, 15.19, 20.85, 19.15, 19.01,
15.24, 16.66, 17.62, 18.22, 17.2 , 15.76, 16.89, 15.22, 18.7 ,
14.84, 14.88, 19.41, 18.54, 17.85, 18.31, 13.68, 18.46, 13.99,
16.38, 16.88, 17.82, 15.17, 15.16, 18.15, 15.08, 15.91, 16.82,
16.85, 18.04, 17.51, 18.44, 15.33, 16.07, 17.22, 15.9 , 18.03,
17.26, 17.6 , 16.77, 17.45, 13.73, 14.95, 15.57, 19.19, 14.39,
15.76])

state = np.random.RandomState(12345)

# сохраните значения 99%-квантилей в переменной values
values = []
for i in range(1000):
subsample = data.sample(frac=1, replace=True, random_state=state)
values.append(subsample.quantile(0.99))

values = pd.Series(values)

lower = values.quantile(0.05)
upper = values.quantile(0.95)

print(lower)
print(upper)

Бутстреп для анализа A/B-теста

Проанализируем две выборки и проверим гипотезу о том, что средний чек увеличился.

import pandas as pd
import numpy as np

# данные контрольной группы A
samples_A = pd.Series([
98.24, 97.77, 95.56, 99.49, 101.4 , 105.35, 95.83, 93.02,
101.37, 95.66, 98.34, 100.75, 104.93, 97. , 95.46, 100.03,
102.34, 98.23, 97.05, 97.76, 98.63, 98.82, 99.51, 99.31,
98.58, 96.84, 93.71, 101.38, 100.6 , 103.68, 104.78, 101.51,
100.89, 102.27, 99.87, 94.83, 95.95, 105.2 , 97. , 95.54,
98.38, 99.81, 103.34, 101.14, 102.19, 94.77, 94.74, 99.56,
102. , 100.95, 102.19, 103.75, 103.65, 95.07, 103.53, 100.42,
98.09, 94.86, 101.47, 103.07, 100.15, 100.32, 100.89, 101.23,
95.95, 103.69, 100.09, 96.28, 96.11, 97.63, 99.45, 100.81,
102.18, 94.92, 98.89, 101.48, 101.29, 94.43, 101.55, 95.85,
100.16, 97.49, 105.17, 104.83, 101.9 , 100.56, 104.91, 94.17,
103.48, 100.55, 102.66, 100.62, 96.93, 102.67, 101.27, 98.56,
102.41, 100.69, 99.67, 100.99])

# данные экспериментальной группы B
samples_B = pd.Series([
101.67, 102.27, 97.01, 103.46, 100.76, 101.19, 99.11, 97.59,
101.01, 101.45, 94.8 , 101.55, 96.38, 99.03, 102.83, 97.32,
98.25, 97.17, 101.1 , 102.57, 104.59, 105.63, 98.93, 103.87,
98.48, 101.14, 102.24, 98.55, 105.61, 100.06, 99. , 102.53,
101.56, 102.68, 103.26, 96.62, 99.48, 107.6 , 99.87, 103.58,
105.05, 105.69, 94.52, 99.51, 99.81, 99.44, 97.35, 102.97,
99.77, 99.59, 102.12, 104.29, 98.31, 98.83, 96.83, 99.2 ,
97.88, 102.34, 102.04, 99.88, 99.69, 103.43, 100.71, 92.71,
99.99, 99.39, 99.19, 99.29, 100.34, 101.08, 100.29, 93.83,
103.63, 98.88, 105.36, 101.82, 100.86, 100.75, 99.4 , 95.37,
107.96, 97.69, 102.17, 99.41, 98.97, 97.96, 98.31, 97.09,
103.92, 100.98, 102.76, 98.24, 97. , 98.99, 103.54, 99.72,
101.62, 100.62, 102.79, 104.19])

# фактическая разность средних значений в группах
AB_difference = samples_B.mean()-samples_A.mean()# < напишите код здесь >
print("Разность средних чеков:", AB_difference)

alpha = 0.05

state = np.random.RandomState(12345)

bootstrap_samples = 1000
count = 0
for i in range(bootstrap_samples):
# объедините выборки
united_samples = pd.concat([samples_A, samples_B])# < напишите код здесь >

# создайте подвыборку
subsample = united_samples.sample(frac=1, replace=True, random_state=state)# < напишите код здесь >

# разбейте подвыборку пополам
subsample_A = subsample[:len(samples_A)]# < напишите код здесь >
subsample_B = subsample[len(samples_A):]# < напишите код здесь >

# найдите разницу средних
bootstrap_difference = subsample_B.mean()-subsample_A.mean()# < напишите код здесь >

# если разница не меньше фактической, увеличиваем счётчик
if bootstrap_difference >= AB_difference:
count += 1

# p-value равно доле превышений значений
pvalue = 1. * count / bootstrap_samples
print('p-value =', pvalue)

if pvalue < alpha:
print("Отвергаем нулевую гипотезу: скорее всего, средний чек увеличился")
else:
print("Не получилось отвергнуть нулевую гипотезу: скорее всего, средний чек не увеличился")