ЛР2
EDA: рассматриваем данные

Раздел 2 · 3 балла

EDA: рассматриваем данные

Разбираем графики, которые Colab строит сам, отделяем полезные от бесполезных, придумываем гипотезу и строим свой график, чтобы её проверить.

EDA
Разведочный анализ данных: первый осмотр таблицы глазами и графиками, до всяких моделей.
Гипотеза
Предположение, которое можно проверить данными. Например: «семьи с детьми тратят меньше».
Гистограмма
Столбики: сколько клиентов попало в каждый интервал значений.
Scatter
Точечный график: каждый клиент это точка, по осям два его свойства.
Выброс
Значение, которое резко отличается от остальных. Пример: доход 666666 при обычных 30-80 тыс.
Медиана
Середина: половина значений меньше, половина больше. Выбросы на неё почти не влияют, в отличие от среднего.
На пальцах. Перед готовкой открываешь холодильник и смотришь, что там лежит, что испортилось и чего не хватает. EDA это такой же осмотр данных.

Графики Colab: что полезно, что нет

Автоматические графики Colab по таблице people
Таблица people. Полезны гистограммы year_birth и income (видны выбросы) и столбики образования и семейного положения. Всё с id и все линии «по номеру строки» это шум.
Автоматические графики Colab по таблице products
Таблица products. Гистограммы трат сильно скошены: высокий столбик у нуля и длинный хвост вправо. Scatter «фрукты против мяса» показывает связь: кто тратит на одно, тратит и на другое.
Автоматические графики Colab по таблице purchases
Таблица purchases. Количества покупок это целые числа, поэтому точки на scatter лежат ровной сеткой и плотность не видна.
БесполезныеПочему
Всё с id (гистограмма id, id vs year_birth, education vs id)id это номер, а не величина. Клиент №5 не «меньше» клиента №6
Линии «по номеру строки» (id, income, mntwines...)Порядок строк в файле случайный, соединять соседей линией бессмысленно
kidhome vs teenhome, гистограмма kidhomeВсего 3 значения (0, 1, 2), точки лежат друг на друге
Scatter целых количеств покупокСетка точек, не видно, где их много
ПолезныеЧто видно
Гистограммы year_birth, incomeВыбросы: годы рождения около 1893-1900, доход 666666
Столбики education, marital_statusБольше всего Graduation и Married; странные категории Alone (3), Absurd (2), YOLO (2)
Гистограммы трат mnt...Большинство тратит мало, немногие очень много
Scatter трат друг против другаПоложительная связь между категориями
year_birth vs incomeВозраст почти не влияет на доход

Гипотеза

Клиенты с детьми тратят в магазине заметно меньше, чем без детей. Возможная причина: у семей с детьми ниже доход. Чтобы это проверить, строим новый график, которого у Colab нет: траты в зависимости от числа детей.

Boxplot (ящик с усами)
Линия в коробке = медиана; коробка = средняя половина клиентов; усы = обычный разброс; отдельные кружки = выбросы.
spend_cols = ['mntwines', 'mntfruits', 'mntmeatproducts',
              'mntfishproducts', 'mntsweetproducts', 'mntgoldprods']

eda = pd.merge(people, products, on='id')
eda['total_spent'] = eda[spend_cols].sum(axis=1)       # сколько клиент потратил всего
eda['children'] = eda['kidhome'] + eda['teenhome']     # всего детей и подростков дома
eda = eda[eda['income'] < 200000]                      # убираем выброс income = 666666

fig, axs = plt.subplots(1, 2, figsize=(14, 5))
sns.boxplot(data=eda, x='children', y='total_spent', hue='children',
            palette='viridis', legend=False, ax=axs[0])
...  # подписи осей и заголовок
sns.scatterplot(data=eda, x='income', y='total_spent', hue='children',
                palette='viridis', s=15, ax=axs[1])
...
plt.show()
print(eda.groupby('children')[['total_spent', 'income']].median())
  1. pd.merge(people, products, on='id') склеиваем анкету и траты по номеру клиента. Здесь можно: запрет на join был только в разделе pandas/SQL.
  2. eda[spend_cols].sum(axis=1) складываем 6 трат в каждой строке (axis=1 = «вдоль строки»). Получаем общую сумму трат клиента.
  3. kidhome + teenhome всего детей и подростков дома: от 0 до 3.
  4. eda[eda['income'] < 200000] убираем выброс 666666, иначе ось доходов растянется и всё сожмётся в угол.
  5. plt.subplots(1, 2) холст на две картинки рядом: axs[0] левая, axs[1] правая.
  6. sns.boxplot(x='children', y='total_spent') по ящику трат на каждое число детей.
  7. sns.scatterplot(x='income', y='total_spent', hue='children') точка на клиента, цвет = число детей.
  8. groupby('children')[...].median() медиана трат и дохода для каждого числа детей.
Слева boxplot трат по числу детей, справа scatter доход и траты
Слева: ящик «0 детей» намного выше остальных. Справа: траты растут вместе с доходом, а тёмные точки (без детей) собраны справа вверху.
Детей домаМедиана тратМедиана дохода
0118972190
130647216
29444065
38044277

Вывод

Ловушка. Связь не доказывает причину. Поэтому мы и сравнили людей с одинаковым доходом: так исключили «дело только в деньгах».

Вопросы на защите

Какие графики Colab бесполезны и почему?

Всё с id (это номер, а не величина) и линии по номеру строки (порядок строк ничего не значит).

Почему медиана, а не среднее?

Траты сильно скошены: несколько клиентов тратят огромные суммы и тянут среднее вверх. Медиана показывает «типичного» клиента.

Зачем убрал доход больше 200000?

Там выброс 666666. Он растягивает ось и сплющивает график, а на вывод не влияет.

Чем твой график отличается от графиков Colab?

Colab строит графики по одной таблице и по исходным столбцам. Я сложил новые признаки (общие траты, число детей) из двух таблиц и сравнил группы ящиками.

Одна фразаГипотеза «дети уменьшают траты» подтвердилась: медиана трат 1189 без детей против 306 с одним ребёнком, и разница остаётся даже при одинаковом доходе.