В этом параграфе мы покажем полезные методы, которые помогут вам лучше планировать и обрабатывать результаты экспериментов.
Начнём со случайной выборки.
Случайная выборка
Возможность получить случайную выборку бывает очень полезной при подготовке экспериментов. В Python
это можно сделать с помощью одной строчки.
🔍 Случайная выборка — наблюдения, отобранные из другой выборки или генеральной совокупности случайным образом
Представьте, что мы рассматриваем данные о влиянии препаратов против тревоги на память человека. В них присутствует три наблюдаемых группы пациентов, которые принимают:
- препараты для длительного приема;
- препараты для краткосрочного приема;
- плацебо.
Для каждого участника записаны результаты тестирования памяти до курса приема таблеток и после. Подготовим наши данные и загрузим нужные пакеты. Датасет доступен по ссылке.
import pandas as pd
df = pd.read_csv('islander_data.csv')
Выберем сто случайных строк из данных. Это легко сделать с помощью метода sample()
. Необходимо просто уточить необходимое количество наблюдений.
exp_sample = df.sample(n=100)
print(exp_sample)
first_name last_name age Happy_Sad_group Dosage Drug Mem_Score_Before \
119 Mitsuku Durand 29 H 3 S 55.9
61 Nina Rodriguez 34 H 3 A 72.6
142 Shauna Durand 65 H 1 T 50.9
18 Takuya Price 44 S 1 A 74.3
182 Ellen Durand 63 S 3 T 67.2
.. ... ... ... ... ... ... ...
125 Michael Lopez 33 H 3 S 36.3
44 Felipe Takahashi 28 H 2 A 60.9
8 Josefa Durand 29 H 1 A 56.2
50 Benjamin Durand 47 S 3 A 41.9
146 David Lopez 29 H 1 T 40.7
Mem_Score_After Diff
119 60.8 4.9
61 77.2 4.6
142 41.8 -9.1
18 65.4 -8.9
182 64.9 -2.3
.. ... ...
125 40.3 4.0
44 64.9 4.0
8 45.0 -11.2
50 55.6 13.7
146 39.0 -1.7
[100 rows x 9 columns]
Однако в таком случае мы не учли, что у нас есть три разных группы на основании того, какое лекарство принимают участники эксперимента. Мы можем просто использовать известный вам метод groupby()
, а потом выбрать в каждой группе по тридцать случайных наблюдений. Проверим сразу, что мы все сделали правильно.
exp_sample = df.groupby('Drug').sample(30)
print(exp_sample.value_counts('Drug'))
Drug
A 30
S 30
T 30
dtype: int64
В pandas
мы легко можем сделать случайную выборку, в том числе, учитывая необходимость сгруппировать наблюдения.
Квантильный график
С квантильным графиком вы уже знакомились в параграфе 5.2. Но коротко напомним, что он позволяет графически проверить нормальность распределения данных. Значение определенного квантиля — это такое значение, которое не превышает некоторая заданная доля от числа всех наблюдений. Например, если значение 25% квантиля равно 75, то это значит, что 25% значений в выборке будут меньше, чем 75. Это ничего не говорит нам о больших значениях: они могут равняться и ста, и тысяче, и десяти тысячам.
Квантильный график создается функцией qqplot
из пакета statsmodels
. В свойствах функции задаем параметр line
равным 45
. У этого числа чисто геометрический смысл: оно делит угол между двумя осями графика пополам. Чем ближе точки лежат вдоль этой линии, тем меньше различий между теоретическим и фактическим распределением. И наоборот.
Посмотрим, как для квантильного графика выглядит идеальный результат. Для этого сгенерируем нормально распределенные значения с помощью numpy
и визуализируем его с помощью qqplot
.
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
normal_data = np.random.normal(0,1, 1000)
sm.qqplot(normal_data, line='45')
plt.show()
На этом графике зелёными точками обозначены наблюдения. Мы видим, что практически все наблюдения вытянуты вдоль линии, что соответствует нормальному распределению.
Теперь проверим наши данные. Основная переменная, интересующая нас — разница между результатами теста на память до и после приема препаратов.
sm.qqplot(df['Diff'], line='45')
plt.show()
Тут наоборот, мы видим, что данные распределены неравномерно. Они пересекают линию ожидаемых значений нормальности почти поперек. Наши дальнейшие действия зависят от того, почему мы проверяли нормальность распределения. Обычно в такой ситуации придется подумать о выборе непараметрического теста.
Визуализация тестов
Вначале мы сказали, что в основе экспериментов должен быть тест. Мы не будем останавливаться на проведение тестов в Python, потому что нам пришлось бы просто пересказать параграф 3.3. Вместо это мы расскажем о том, как мы можем визуализировать тесты.
T-тест
T-тест проверяет, значима ли разница средних между двумя группами. Мы можем использовать бокс-плот, чтобы получить график, который сможет проиллюстрировать результаты теста.
Если нам нужно представить распределение значений непрерывной переменной в разных группах, то можно использовать бокс-плот. Визуализируем распределения результатов теста на память для двух групп пациентов: у первой были вызваны счастливые воспоминания за десять минут до тестирования, а у второй — грустные. Это легко сделать с помощью команды boxplot
из pandas
.
exp_sample.boxplot(by = 'Happy_Sad_group', column =['Diff'], grid = False)
Напомним, что график состоит из медианы, коробки, усов и аутлаеров. Коробка — это прямоугольник, который отражает первый и третий квартиль распределения, что примерно равно 68% процентов распределения. Усы показывают диапазон распределения 95% результатов.
График показывает, что в группе тех, кто испытывал счастливые воспоминания до тестирования оказался гораздо меньший разброс по результатам теста. Изменение их памяти лежит, в основном, в диапазоне от -10 до +10. В группе тех, кто вспоминал грустные события, диапазон гораздо шире и у некоторых людей память улучшается значительнее. Тем не менее медианные значения у них примерно одинаковые и графически видно, что значимой разницы средних между группами не наблюдается.
Такой график и интерпретация может сопровождать результаты теста. Визуализация делает его наглядным для читателя.
ANOVA
Аналогичный график мы можем построить и для визуализации теста ANOVA. Средние в 3 и более группах графически можно сравнить таким же образом. Посмотрим на разницу результатов теста на память в зависимости от групп принимаемого лекарства:
- препараты длительного приема (A);
- препараты кратковременного приема (T);
- плацебо (S).
exp_sample.boxplot(by = 'Drug', column =['Diff'], grid = False)
У препаратов длительного приема оказался наибольший положительный эффект на память. Плацебо и препараты кратковременного приема не сильно отличаются друг от друга, график подтверждает отсутствие значимой разницы.
Хи-квадрат
В хи-квадрате мы сравниваем соотношения двух категориальных переменных. Для визуализации этого теста мы можем использовать мозаичный график — красивый и наглядный способ отражения. Представим сравнение групп испытуемых, которые до тестирования имели грустные и веселые мысли и группы дозировки: 1 — маленькая дозировка, 2 — средняя, 3 — большая.
В statsmodels
есть метод mosaic
. Внутри метода указываем датафрейм и список с категориальными переменными. В параметре title
зададим название графика.
from statsmodels.graphics.mosaicplot import mosaic
mosaic(exp_sample, ['Dosage','Happy_Sad_group'], title = 'Соотношения групп дозировки в группе людей со счастливыми и грустными воспоминаниями')
Мозаичный график показывает пропорции между категориями. Из него мы видим, что в группах с самой большой дозировкой, было наибольшее количество людей со счастливыми воспоминаниями. С уменьшением дозировки, число людей с грустными воспоминаниями постепенно увеличивается. Мы можем развить эту мысль: и проверить, действительно ли есть статистически значимая разница.
Визуализация корреляции
Как мы помним, корреляция — это показатель, который показывает взаимное изменение значений двух непрерывных переменных. Диаграмма рассеяния позволяет показать, как распределяются их значения. Взглянем, как результаты тестирования на память изменяются вместе с возрастом. Используем метод scatter()
из matplotlib
. Мы уже сталкивались с ним в параграфе 5.3. Зададим осям названия.
plt.scatter(exp_sample['age'], exp_sample['Diff'])
plt.xlabel('Возраст')
plt.ylabel('Результаты теста после эксперимента')
plt.show()
Здесь можно наблюдать некоторый разброс и не очень понятен коэффициент корреляции. Мы можем его выяснить с помощью добавления кривой корреляции. Она будет отражать коэффициент корреляции. numpy
позволит нам рассчитать наклон и начальную точку линии.
plt.scatter(exp_sample['age'], exp_sample['Diff'])
plt.xlabel('Возраст')
plt.ylabel('Результаты теста после эксперимента')
k, b = np.polyfit(exp_sample['age'], exp_sample['Diff'], 1)
plt.plot(exp_sample['age'], k*exp_sample['age']+b)
Мы видим, что наклон небольшой. Это позволяет визуализировать тот факт, что коэффициент корреляции между этими переменными близок к 0. Можно подтвердить это, посчитав коэффициент.
>>> np.corrcoef(exp_sample['age'], exp_sample['Diff'])[0, 1]
0.06431149195434109
Действительно, коэффициент очень незначителен и близок к 0. Наклон равный 45 градусам обозначал бы идеальную корреляцию. Но здесь мы видим прямую линию, которая говорит нам о том, что это распределение не является нормальным.
Теперь вы умеете не только проводить эксперименты, но и визуализировать их результаты. Это важный навык, который поможет вам сделать выводы ещё более убедительными.
В следующем разделе мы поговорим о том, как правильно обогащать данные (и зачем это нужно), а кроме того научим вас пользоваться ещё одним мощным инструментом для анализа, — линейной регрессией, — и закрепим знания на практике.