Парадокс Симпсона — статистический парадокс, согласно которому фактор, больше проявляющийся при любых фоновых условиях, чем противоположный ему, проигрывает менее эффективному, но относительно часто встречающемуся фактору.
Познакомлю вас с понятиями категоризации данных и парадокс Симпсона. Для начала давайте посмотрим что за метод будет использоваться сегодня.
Небольшая преамбула: метод value_counts()
, который мы сейчас будем использовать, определяет уникальные значения и возвращает таблицу, где подсчитывает, сколько раз они встретились в серии, причем в нисходящем порядке. У этого метода есть несколько параметров, такие как нормализация, сортировка, отображение восходящем порядке, категоризация и исключение ячейки с отсутствующим значением. Посмотрите, в правой части слайда мы создаем серию под названием index
и присваиваем ей набор целочисленных значений и включаем одно отсутствующее, затем, используя метод value_counts()
, мы определяем сколько раз то или иное число встретилась в этой серии. Допустим, цифра 3 встретилась дважды. Теперь мы хотим определить удельный вес каждого значения в этой серии, используя normalize = True
, просим пересчитать результирующую серию и отобразить не количество упоминаний, а пропорцию. Если суммировать все цифры второго столбца, то мы получим единицу, то есть цифра 3 занимает 40 процентов место в этой серии.
Для начала импортируем все необходимые библиотеки. Импортируем модуль pandas.plotting для отображения графиков. Импортируем SciPy и набор статистических методов. Импортируем matplotlib и модуль pyplot. используем директиву %matplotlib inline
, чтобы график строился все в той же оболочки Colab, но отображался как картинка:
import numpy as np
import csv
import pandas as pd
import pandas.plotting
import scipy.stats
import matplotlib
import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
%matplotlib inline
Создадим переменную smoking
и вычитаем с помощью метода read_csv()
данные о влиянии курения на продолжительность жизни:
smoking = pd.read_csv('https://www.dropbox.com/s/jjjhzvnackds0h9/уикхем.csv?dl=1')
С помощью ранее изученного нами метода value_counts()
определим количество выживших и невыживших, обратившись к параметру outcome (выживаемость):
pd.DataFrame(smoking.outcome.value_counts())
Итак, на момент окончания исследования из всей контрольной группы выживших девятьсот сорок пять человек, не выживших – 369:
Отобразим в процентах то есть пропорциях с помощью нормализации. С помощью метода groupby()
, метода value_counts()
, нормализации:
bysmoker = smoking.groupby('smoker').outcome.value_counts(normalize = True)
bysmoker.unstack()
На момент окончания исследования исследования живых курильщиков 76%:
Сейчас пока не очень понятно, но я вам покажу, как сделать эти данные нагляднее и делать выводы. Мы категоризируем группы респондентов, используя специальный метод pd.cut()
, и разделим группы корреспондентов на такие диапазоны: от 0 до 30 лет, от 31 до 40, от 41 до 50, от 51-64, 64 и старше:
smoking['ageGroup'] = pd.cut(smoking.age,[0, 30, 40, 53, 64, 120], labels = ['0-30', '31-40', '41-52', '53-63', '64+'])
smoking['ageGroup'].head()
Посмотрим, что получилось:
0 0-30
1 0-30
2 64+
3 64+
4 53-63
Name: ageGroup, dtype: category
Categories (5, object): ['0-30' < '31-40' < '41-52' < '53-63' < '64+']
Теперь отобразим количество выживших курильщиков и не курильщиков в каждый из возрастных групп. Создадим переменную byage
, посчитаем уникальные значения в каждой из возрастных категорий и нормализуем это все, то есть отобразим пропорции:
byage = smoking.groupby(['ageGroup', 'smoker']).outcome.value_counts(normalize = True)
byage.unstack().drop('Dead', axis = 1)
Смотрите, здесь взаимосвязь между курением и выживаемости уже более очевидна: если на молодых людей в возрасте от 0 до 30 и от 31 до 40 курение почти никак не влияет, то в трех остальных возрастных группах шансы выжить уже значительно меньше:
Причем самой опасной возрастной группой является диапазон с 53 до 64 лет. Это явление получило название "Парадокс Симпсона": разбив данные на категории, мы наконец-то увидели взаимосвязь между выживаемостью и курением.
Сделаем эти данные нагляднее, построим несколько графиков.
Начнем с двойной гистограмма. Она у нас размером 10 на 4. Первый график будет занимать на холсте место, определяемое этими тремя параметрами. Мы используем метод value_counts()
и построим гистограмму, обозначаемую словом bar, окрасим ее, определим название:
plt.figure(figsize = (10, 4))
plt.subplot(1, 2, 1);
smoking.smoker.value_counts().plot(kind = 'bar');
Зададим внешний вид второго графика, изменив немного цвета, название, местоположение на холсте:
plt.figure(figsize = (10, 4))
plt.subplot(1, 2, 2);
smoking.smoker.value_counts().plot(kind = 'bar');
Теперь построим круговую диаграмму. Копируем код выше и изменим тип графика на круговой (pie
):
plt.figure(figsize = (10, 4))
plt.subplot(1, 2, 1);
smoking.smoker.value_counts().plot(kind = 'pie', colors =['C0', 'C1']);
plt.title = 'Выживших'
plt.subplot(1, 2, 2);
smoking.smoker.value_counts().plot(kind = 'pie', colors = ['C2', 'C3']);
plt.title = 'Курильщиков'
bysmoker.plot(kind = 'bar')
Ярлыки путают карты, мешают воспринимать данные, потому немного видоизменим внешний вид этой гистограммы:
bysmoker.unstack().plot(kind = 'bar', stacked = True)
Параметр stacked = true
, состыковывает эти данные в высотную шкалу, где легко можно судить о пропорции. Теперь визуализируем возрастную группировку:
byage.unstack().plot(kind = 'bar', stacked = True)
Как вы видите, отрыв от предыдущей группы наиболее ярко выражен в возрастных группах "53 - 64" и "64 и старше" лет.
Ноутбук, не требующий дополнительной настройки на момент написания статьи, можно скачать здесь.
© Лена Капаца. Все права защищены.