{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python для анализа данных\n", "\n", "Перед изучением убедитесь, что вы достаточно хорошо ознакомились с первой частью нашего материала про pandas.\n", "\n", "## Операции в pandas" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "import scipy.stats as sps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Простые операции" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Сгенерируем случайные числа и представим их в виде `DataFrame`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCD
0-1.3457021.5832710.480914-0.053891
1-1.5132220.3896560.448918-0.265700
20.817235-1.573969-0.0808602.160590
3-0.7731100.5697150.078057-0.215249
4-0.1781110.2865180.0358250.805861
50.849732-0.182298-0.2240150.208410
6-1.701552-0.586663-1.3136440.470541
7-0.373508-0.813824-0.251265-0.834696
8-0.745802-0.160359-0.934386-0.358681
9-1.1161770.229204-2.352976-0.348601
\n", "
" ], "text/plain": [ " A B C D\n", "0 -1.345702 1.583271 0.480914 -0.053891\n", "1 -1.513222 0.389656 0.448918 -0.265700\n", "2 0.817235 -1.573969 -0.080860 2.160590\n", "3 -0.773110 0.569715 0.078057 -0.215249\n", "4 -0.178111 0.286518 0.035825 0.805861\n", "5 0.849732 -0.182298 -0.224015 0.208410\n", "6 -1.701552 -0.586663 -1.313644 0.470541\n", "7 -0.373508 -0.813824 -0.251265 -0.834696\n", "8 -0.745802 -0.160359 -0.934386 -0.358681\n", "9 -1.116177 0.229204 -2.352976 -0.348601" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.DataFrame(sps.norm.rvs(size=(10, 4)), \n", " columns=['A', 'B', 'C', 'D'])\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выведем описательные статистики по столбцам — количество значений, среднее, стандартное отклонение (корень из дисперсии), минимум, квантили, максимум." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCD
count10.00000010.00000010.00000010.000000
mean-0.608022-0.025875-0.4113430.156858
std0.8981490.8598380.8821210.843477
min-1.701552-1.573969-2.352976-0.834696
25%-1.288321-0.485572-0.763606-0.327876
50%-0.7594560.034423-0.152438-0.134570
75%-0.2269600.3638710.0674990.405008
max0.8497321.5832710.4809142.160590
\n", "
" ], "text/plain": [ " A B C D\n", "count 10.000000 10.000000 10.000000 10.000000\n", "mean -0.608022 -0.025875 -0.411343 0.156858\n", "std 0.898149 0.859838 0.882121 0.843477\n", "min -1.701552 -1.573969 -2.352976 -0.834696\n", "25% -1.288321 -0.485572 -0.763606 -0.327876\n", "50% -0.759456 0.034423 -0.152438 -0.134570\n", "75% -0.226960 0.363871 0.067499 0.405008\n", "max 0.849732 1.583271 0.480914 2.160590" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Среднее по столбцам" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "A -0.608022\n", "B -0.025875\n", "C -0.411343\n", "D 0.156858\n", "dtype: float64" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Оценка матрицы корреляций значений в столбцах" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCD
A1.000000-0.5243310.2105870.522391
B-0.5243311.0000000.240015-0.474598
C0.2105870.2400151.0000000.154964
D0.522391-0.4745980.1549641.000000
\n", "
" ], "text/plain": [ " A B C D\n", "A 1.000000 -0.524331 0.210587 0.522391\n", "B -0.524331 1.000000 0.240015 -0.474598\n", "C 0.210587 0.240015 1.000000 0.154964\n", "D 0.522391 -0.474598 0.154964 1.000000" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.corr()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Применение функции к данным.\n", "Для примера посчитаем разброс значений — разница максимума и минимума." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "A 2.551284\n", "B 3.157239\n", "C 2.833890\n", "D 2.995285\n", "dtype: float64" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.apply(lambda x: x.max() - x.min())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Объединение таблиц\n", "\n", "#### 2.1 Функция `df.append`\n", "\n", "Добавление строк в виде таблицы `other` в таблицу `df`. При наличии у новых строк колонок, которых нет в таблице, они добавляются в таблицу.\n", "\n", "`df.append(other, ignore_index=False, verify_integrity=False, sort=None)`\n", "\n", "* `df` — таблица;\n", "* `other` — добавляемые строки в виде таблицы;\n", "* `ignore_index` — сохранить индексы или определить и как $0, ..., n-1$;\n", "* `verify_integrity` — если `True`, то создает исключение в случае повторения индексов;\n", "* `sort` — сортировать ли колонки, если они (или их порядок) различаются.\n", "\n", "---------------\n", "\n", "Создадим новую таблицу из первых четырех строк таблицы `df`. В новую таблицу добавим колонку `flag`, в которую запишем условие, что число в столбце D положительно. Затем добавим строки из новой таблицы к старой. Полученная таблица содержит пропуски, которые отмечены как `NaN`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCDflag
0-1.3457021.5832710.480914-0.053891NaN
1-1.5132220.3896560.448918-0.265700NaN
20.817235-1.573969-0.0808602.160590NaN
3-0.7731100.5697150.078057-0.215249NaN
4-0.1781110.2865180.0358250.805861NaN
50.849732-0.182298-0.2240150.208410NaN
6-1.701552-0.586663-1.3136440.470541NaN
7-0.373508-0.813824-0.251265-0.834696NaN
8-0.745802-0.160359-0.934386-0.358681NaN
9-1.1161770.229204-2.352976-0.348601NaN
10-1.3457021.5832710.4809140.002904False
11-1.5132220.3896560.4489180.070597False
120.817235-1.573969-0.0808604.668147True
13-0.7731100.5697150.0780570.046332False
\n", "
" ], "text/plain": [ " A B C D flag\n", "0 -1.345702 1.583271 0.480914 -0.053891 NaN\n", "1 -1.513222 0.389656 0.448918 -0.265700 NaN\n", "2 0.817235 -1.573969 -0.080860 2.160590 NaN\n", "3 -0.773110 0.569715 0.078057 -0.215249 NaN\n", "4 -0.178111 0.286518 0.035825 0.805861 NaN\n", "5 0.849732 -0.182298 -0.224015 0.208410 NaN\n", "6 -1.701552 -0.586663 -1.313644 0.470541 NaN\n", "7 -0.373508 -0.813824 -0.251265 -0.834696 NaN\n", "8 -0.745802 -0.160359 -0.934386 -0.358681 NaN\n", "9 -1.116177 0.229204 -2.352976 -0.348601 NaN\n", "10 -1.345702 1.583271 0.480914 0.002904 False\n", "11 -1.513222 0.389656 0.448918 0.070597 False\n", "12 0.817235 -1.573969 -0.080860 4.668147 True\n", "13 -0.773110 0.569715 0.078057 0.046332 False" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "other = df[:4].copy() # Полное копирование\n", "other['flag'] = other['D'] > 0\n", "other['D'] = other['D'] ** 2\n", "\n", "df.append(other, ignore_index=True, sort=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Функция `pd.concat`\n", "\n", "Соединение таблиц вдоль выбранной оси\n", "\n", "`pd.concat(objs, axis=0, join='outer', ignore_index=False, copy=True, ...)`\n", "\n", "* `objs` — объединяемые таблицы;\n", "* `axis` : {`0` или `'index'`, `1` или `'columns'`} — ось индексов или ось колонок, иными словами соединение по вертикали или по горизонтали;\n", "* `join` : {`'inner'`, `'outer'`} — тип объединения — пересечение или объединение индексов/колонок;\n", "* `ignore_index` — сохранить индексы или определить и как $0, ..., n-1$;\n", "* `copy` — копировать данные или нет.\n", "\n", "------------\n", "\n", "Простой пример соединения таблиц:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCD
0-1.3457021.5832710.480914-0.053891
1-1.5132220.3896560.448918-0.265700
20.817235-1.573969-0.0808602.160590
3-0.7731100.5697150.078057-0.215249
4-0.1781110.2865180.0358250.805861
50.849732-0.182298-0.2240150.208410
6-1.701552-0.586663-1.3136440.470541
7-0.373508-0.813824-0.251265-0.834696
8-0.745802-0.160359-0.934386-0.358681
9-1.1161770.229204-2.352976-0.348601
\n", "
" ], "text/plain": [ " A B C D\n", "0 -1.345702 1.583271 0.480914 -0.053891\n", "1 -1.513222 0.389656 0.448918 -0.265700\n", "2 0.817235 -1.573969 -0.080860 2.160590\n", "3 -0.773110 0.569715 0.078057 -0.215249\n", "4 -0.178111 0.286518 0.035825 0.805861\n", "5 0.849732 -0.182298 -0.224015 0.208410\n", "6 -1.701552 -0.586663 -1.313644 0.470541\n", "7 -0.373508 -0.813824 -0.251265 -0.834696\n", "8 -0.745802 -0.160359 -0.934386 -0.358681\n", "9 -1.116177 0.229204 -2.352976 -0.348601" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([df[:5], df[5:]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.3 Функции `pd.merge` и `df.join`\n", "\n", "Слияние таблиц по вертикали путем выполнения операций слияния баз данных в стиле SQL.\n", "\n", "`pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, suffixes=('_x', '_y'), ...)`\n", "\n", "* `left` и `right` — объединяемые таблицы.\n", "* `how` — тип объединения:\n", " * `left` — только по ключам из левой таблицы == *SQL left outer join*;\n", " * `right` — только по ключам из правой таблицы == *SQL right outer join*;\n", " * `outer` — по объединению ключей == *SQL full outer join*;\n", " * `inner` — по пересечению ключей == *SQL inner join*.\n", "* `on` — имя (или имена) колонок, по которым будет производиться объединение (т.е. ключи). Если их несколько, то нужно передать список имен. Имена колонок в таблице должны совпадать.\n", "* `left_on` и `right_on` — аналогично `on` для случая, когда в таблицах различаются имена колонок, соответствующие ключам.\n", "* `left_index` и `right_index` — использовать ли индексы в качестве ключей.\n", "* `suffixes` — суффиксы, которые будут добавлены к тем колонкам, имена которых повторяются.\n", "\n", "*Пример.* Опция `how=left, left_on='A', right_on='B'` соответствует взятию всех строк из таблицы `left`, а из таблицы `right` берутся те строки, в которых значения в колонке `A` таблицы `left` совпадает со значением колонки `B` таблицы `right`. Если в одной из таблиц таких значений несколько, то строки другой таблицы дублируются. Если в таблице `right` каких-то значений нет, то в результирующей таблице будут пропуски.\n", "\n", "`df.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)`\n", "\n", "* `df` — основная таблица. В качестве ключей используется индекс.\n", "* `other` — другая таблица.\n", "* `on` — колонка(-и) в `other`, соответствующая ключам, по ним происходит объедиенение. Если `None`, то используется индекс.\n", "* `how` — тип объединения (см. `pd.merge`).\n", "* `lsuffix` и `rsuffix` — суффиксы, которые будут добавлены к тем колонкам, имена которых повторяются." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "------------------\n", "\n", "##### Пример 1.\n", "\n", "В обеих таблицах ключи повторяются" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "left = pd.DataFrame({'key': ['A', 'A'], \n", " 'lval': [1, 2]})\n", "right = pd.DataFrame({'key': ['A', 'A'], \n", " 'rval': [4, 5]})" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keylval
0A1
1A2
\n", "
" ], "text/plain": [ " key lval\n", "0 A 1\n", "1 A 2" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "left" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keyrval
0A4
1A5
\n", "
" ], "text/plain": [ " key rval\n", "0 A 4\n", "1 A 5" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "right" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В результате объединения получаем 4 строки — для каждой строки из левой таблице есть две строки из правой таблицы с таким же ключом." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keylvalrval
0A14
1A15
2A24
3A25
\n", "
" ], "text/plain": [ " key lval rval\n", "0 A 1 4\n", "1 A 1 5\n", "2 A 2 4\n", "3 A 2 5" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, on='key')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###### Пример 2.\n", "\n", "В таблицах ключи не повторяются" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "left = pd.DataFrame({'key': ['A', 'B'], \n", " 'lval': [1, 2]})\n", "right = pd.DataFrame({'key': ['A', 'B'], \n", " 'rval': [4, 5]})" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keylval
0A1
1B2
\n", "
" ], "text/plain": [ " key lval\n", "0 A 1\n", "1 B 2" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "left" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keyrval
0A4
1B5
\n", "
" ], "text/plain": [ " key rval\n", "0 A 4\n", "1 B 5" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "right" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "В результате объединения получаем 2 строки — для каждой строки из левой таблице есть только одна строка из правой таблицы с таким же ключом." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
keylvalrval
0A14
1B25
\n", "
" ], "text/plain": [ " key lval rval\n", "0 A 1 4\n", "1 B 2 5" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, on='key')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###### Пример 3.\n", "\n", "Посмотрим на различные типы объединения. Сооздадим и напечатаем две таблицы." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "left = pd.DataFrame({'lkey': ['A', 'B', 'C', 'A'], \n", " 'value': range(4)})\n", "right = pd.DataFrame({'rkey': ['A', 'B', 'D', 'B'], \n", " 'value': range(4, 8)})" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lkeyvalue
0A0
1B1
2C2
3A3
\n", "
" ], "text/plain": [ " lkey value\n", "0 A 0\n", "1 B 1\n", "2 C 2\n", "3 A 3" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "left" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
rkeyvalue
0A4
1B5
2D6
3B7
\n", "
" ], "text/plain": [ " rkey value\n", "0 A 4\n", "1 B 5\n", "2 D 6\n", "3 B 7" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "right" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Внешнее слияние** — используются ключи из объединения списков ключей. Иначе говоря, используются ключи, которые есть хотя бы в одной из таблиц. Если в другой таблице таких ключей нет, то ставятся пропуски." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lkeyvalue_xrkeyvalue_y
0A0.0A4.0
1A3.0A4.0
2B1.0B5.0
3B1.0B7.0
4C2.0NaNNaN
5NaNNaND6.0
\n", "
" ], "text/plain": [ " lkey value_x rkey value_y\n", "0 A 0.0 A 4.0\n", "1 A 3.0 A 4.0\n", "2 B 1.0 B 5.0\n", "3 B 1.0 B 7.0\n", "4 C 2.0 NaN NaN\n", "5 NaN NaN D 6.0" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, \n", " left_on='lkey', right_on='rkey', how='outer')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Внутреннее слияние** — используются ключи из пересечения списков ключей. Иначе говоря, используются ключи, которые присутствуют в обеих таблицах." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lkeyvalue_xrkeyvalue_y
0A0A4
1A3A4
2B1B5
3B1B7
\n", "
" ], "text/plain": [ " lkey value_x rkey value_y\n", "0 A 0 A 4\n", "1 A 3 A 4\n", "2 B 1 B 5\n", "3 B 1 B 7" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, \n", " left_on='lkey', right_on='rkey', how='inner')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Объединение по ключам левой таблицы.** Не используются ключи, которые есть в правой таблицы, но которых нет в левой. Если в правой таблице каких-то ключей нет, то ставятся пропуски." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lkeyvalue_xrkeyvalue_y
0A0A4.0
1B1B5.0
2B1B7.0
3C2NaNNaN
4A3A4.0
\n", "
" ], "text/plain": [ " lkey value_x rkey value_y\n", "0 A 0 A 4.0\n", "1 B 1 B 5.0\n", "2 B 1 B 7.0\n", "3 C 2 NaN NaN\n", "4 A 3 A 4.0" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, \n", " left_on='lkey', right_on='rkey', how='left')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Объединение по ключам правой таблицы.** Не используются ключи, которые есть в левой таблицы, но которых нет в правой. Если в левой таблице каких-то ключей нет, то ставятся пропуски." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
lkeyvalue_xrkeyvalue_y
0A0.0A4
1A3.0A4
2B1.0B5
3B1.0B7
4NaNNaND6
\n", "
" ], "text/plain": [ " lkey value_x rkey value_y\n", "0 A 0.0 A 4\n", "1 A 3.0 A 4\n", "2 B 1.0 B 5\n", "3 B 1.0 B 7\n", "4 NaN NaN D 6" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, \n", " left_on='lkey', right_on='rkey', how='right')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Выполним внтуреннее объединение и установим ключ качестве индекса" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
value_xvalue_y
lkey
A04
A34
B15
B17
\n", "
" ], "text/plain": [ " value_x value_y\n", "lkey \n", "A 0 4\n", "A 3 4\n", "B 1 5\n", "B 1 7" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left, right, \n", " left_on='lkey', right_on='rkey', how='inner') \\\n", " .set_index('lkey')[['value_x', 'value_y']]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ту же операцию можно выполнить с помощью `join`" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
valuevalue_r
A04
A34
B15
B17
\n", "
" ], "text/plain": [ " value value_r\n", "A 0 4\n", "A 3 4\n", "B 1 5\n", "B 1 7" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "left.set_index('lkey') \\\n", " .join(right.set_index('rkey'), rsuffix='_r', how='inner')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Группировка\n", "\n", "Часто на практике необходимо вычислять среднее по каким-либо категориям или группам в данных. Группа может определяться, например, столбцом в таблице, у которого не так много значений. Мы хотели бы для каждого такого значения посчитать среднее значение другой колонки данных в этой группе.\n", "\n", "Этапы группировки данных:\n", "\n", "* разбиение данных на группы по некоторым критериям;\n", "* применение функции отдельно к каждой группе;\n", "* комбинирование результата в структуру данных.\n", "\n", "Группировка выполняется функцией\n", "\n", "`df.groupby(by=None, axis=0, level=None, sort=True, ...)`\n", "\n", "* `df` — таблица, данные которой должны быть сгруппированы;\n", "* `by` — задает принцип группировки. Чаще всего это имя столбца, по которому нужно сгруппировать. Может так же быть функцией;\n", "* `axis` — ось (0 = группировать строки, 1 = группировать столбцы);\n", "* `level` — если ось представлена мультииндексом, то указывает на уровень мультииндекса;\n", "* `sort` — сортировка результата по индексу.\n", "\n", "Результатом группировки является объект, состоящий из пар (имя группы, подтаблица). Имя группы соответствует значению, по которому произведена группировка. К объекту-результату группировки применимы, например, следующие операции:\n", "\n", "* `for name, group in groupped: ... ` — цикл по группам;\n", "* `get_group(name)` — получить таблицу, соответствующую группе с именем `name`;\n", "* `groups` — получить все группы в виде словаря имя-подтаблица;\n", "* `count()` — количество значений в группах, исключая пропуски;\n", "* `size()` — размер групп;\n", "* `sum()`, `max()`, `min()`;\n", "* `mean()`, `median()`, `var()`, `std()`, `corr()`, `quantile(q)`;\n", "* `describe()` — вывод описательных статистик;\n", "* `aggregate(func)` — применение функции (или списка функций) `func` к группам.\n", "---------" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Создадим таблицу для примера" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ЖивотноеЦвет шерстиРостДлина хвостика
0Котикбелый33.7562628.498897
1Песикбелый35.6341987.056738
2Котиккоричневый30.89202717.375188
3Песикчерный23.2729974.179033
4Котиккоричневый33.00203512.200925
5Песиккоричневый41.04579814.026990
6Котикбелый42.2754207.053550
7Песикчерный31.76193310.652498
\n", "
" ], "text/plain": [ " Животное Цвет шерсти Рост Длина хвостика\n", "0 Котик белый 33.756262 8.498897\n", "1 Песик белый 35.634198 7.056738\n", "2 Котик коричневый 30.892027 17.375188\n", "3 Песик черный 23.272997 4.179033\n", "4 Котик коричневый 33.002035 12.200925\n", "5 Песик коричневый 41.045798 14.026990\n", "6 Котик белый 42.275420 7.053550\n", "7 Песик черный 31.761933 10.652498" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.DataFrame({\n", " 'Животное' : ['Котик', 'Песик', 'Котик', 'Песик',\n", " 'Котик', 'Песик', 'Котик', 'Песик'],\n", " 'Цвет шерсти' : ['белый', 'белый', 'коричневый', 'черный',\n", " 'коричневый', 'коричневый', 'белый', 'черный'],\n", " 'Рост' : sps.gamma(a=12, scale=3).rvs(size=8),\n", " 'Длина хвостика' : sps.gamma(a=10).rvs(size=8)\n", "})\n", "\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Пример 1.\n", "\n", "Если все котики встанут друг на друга, то какой их суммарный рост? А у песиков? А какова суммарная длинна хвостиков у котиков и у песиков?\n", "\n", "Группировка по одной колонке и последующее применение операции суммирования:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
РостДлина хвостика
Животное
Котик139.92574345.12856
Песик131.71492535.91526
\n", "
" ], "text/plain": [ " Рост Длина хвостика\n", "Животное \n", "Котик 139.925743 45.12856\n", "Песик 131.714925 35.91526" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.groupby('Животное').sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Посчитаем описательные статистики для каждого животного" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
РостДлина хвостика
countmeanstdmin25%50%75%maxcountmeanstdmin25%50%75%max
Животное
Котик4.034.9814365.01147230.89202732.47453333.37914835.88605142.2754204.011.2821404.6042317.0535508.13756010.34991113.49449117.375188
Песик4.032.9287317.47888023.27299729.63969933.69806536.98709841.0457984.08.9788154.2824284.1790336.3373128.85461811.49612114.026990
\n", "
" ], "text/plain": [ " Рост \\\n", " count mean std min 25% 50% \n", "Животное \n", "Котик 4.0 34.981436 5.011472 30.892027 32.474533 33.379148 \n", "Песик 4.0 32.928731 7.478880 23.272997 29.639699 33.698065 \n", "\n", " Длина хвостика \\\n", " 75% max count mean std min \n", "Животное \n", "Котик 35.886051 42.275420 4.0 11.282140 4.604231 7.053550 \n", "Песик 36.987098 41.045798 4.0 8.978815 4.282428 4.179033 \n", "\n", " \n", " 25% 50% 75% max \n", "Животное \n", "Котик 8.137560 10.349911 13.494491 17.375188 \n", "Песик 6.337312 8.854618 11.496121 14.026990 " ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.groupby('Животное').describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Пример 2.\n", "\n", "Теперь предположим, что котики и песики встают только на представителей своего вида и своего цвета шерсти. Что тогда будет?\n", "\n", "Группировка по двум колонкам и последующее применение операции суммирования" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
РостДлина хвостика
ЖивотноеЦвет шерсти
Котикбелый76.03168215.552447
коричневый63.89406129.576113
Песикбелый35.6341987.056738
коричневый41.04579814.026990
черный55.03493014.831531
\n", "
" ], "text/plain": [ " Рост Длина хвостика\n", "Животное Цвет шерсти \n", "Котик белый 76.031682 15.552447\n", " коричневый 63.894061 29.576113\n", "Песик белый 35.634198 7.056738\n", " коричневый 41.045798 14.026990\n", " черный 55.034930 14.831531" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.groupby(['Животное', 'Цвет шерсти']).sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Полученная таблица имеет *мультииндекс*" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex([('Котик', 'белый'),\n", " ('Котик', 'коричневый'),\n", " ('Песик', 'белый'),\n", " ('Песик', 'коричневый'),\n", " ('Песик', 'черный')],\n", " names=['Животное', 'Цвет шерсти'])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.groupby(['Животное', 'Цвет шерсти']).sum().index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 4. Таблицы сопряженности (Crosstab) и сводные таблицы (Pivot table)\n", "\n", "**Задача.** В медицинской клинике информацию о приемах записывают в таблицу со следующими полями:\n", "* время приема,\n", "* врач,\n", "* пациент,\n", "* поставленный диагноз,\n", "* назначение,\n", "* другие поля.\n", "\n", "Требуется посчитать, сколько раз за предыдущий месяц каждый врач ставил какой-либо диагноз. Результаты представить в виде таблицы, в которой посчитать также суммы по строкам и столбцам, т.е. сколько врач сделал приемов за месяц и сколько раз конкретный диагноз поставлен всеми врачами.\n", "\n", "Как решать?\n", "\n", "**Способ 1** \n", "1. Группировка по врачам.\n", "2. Для каждого врача группировка по диагнозам.\n", "3. В каждой группе вычисление суммы.\n", "4. Соединение в одну таблицу.\n", "5. Вычисление суммы по столбцам и по строкам.\n", "\n", "Можете прикинуть количество строк кода и время работы 😁\n", "\n", "**Способ 2**\n", "1. Создать пустую таблицу.\n", "2. Циклом 🤣 по всем записям исходной таблицы считать суммы.\n", "3. Вычисление суммы по столбцам и по строкам.\n", "\n", "И снова можете прикинуть количество строк кода и время работы 😁\n", "\n", "**Способ 3**\n", "\n", "Применить умную функцию из pandas, которая сделает все сама!\n", "\n", "---------------" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 4.1 Функция `pd.crosstab`\n", "\n", "Эксель-подобные таблицы сопряженности\n", "\n", "`pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, margins_name='All', dropna=True, normalize=False)`\n", "\n", "* `index` — значения для группировки по строкам;\n", "* `columns` — значения для группировки по столбцам;\n", "* `values` — аггригируемый столбец (или столбцы), его значения непосредственно определяют значения таблицы сопряженности;\n", "* `aggfunc` — функция, которая будет применена к каждой группе значений `values`, сгруппированным по значениям`index` и `columns`. Значения этой функции и есть значения сводной таблицы;\n", "* `rownames` и `colnames` — имена строк и столбцов таблицы сопряженности;\n", "* `margins` — добавляет результирующий столбец/строку;\n", "* `margins_name` — имя результирующего столбец/строку;\n", "* `dropna` — не включать столбцы, которые состоят только из `NaN`;\n", "* `normalize`: `boolean`, {`'all'`, `'index'`, `'columns'`} — нормировка всей таблицы (или только по строкам/столбцам).\n", "\n", "В примере выше:\n", "\n", "`pd.crosstab(df['Врач'], df['Диагноз'], margins=True)`\n", "\n", "#### 4.2 Функция `pd.pivot_table`\n", "\n", "Эксель-подобные сводные таблицы\n", "\n", "`pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')`\n", "\n", "* `data` — исходная таблица;\n", "* `values` — аггригируемый столбец, его значения непосредственно определяют значения сводной таблицы;\n", "* `index` — ключи для группировки, относятся к индексам сводной таблицы;\n", "* `columns` — ключи для группировки, относятся к столбцам сводной таблицы;\n", "* `aggfunc` — функция, которая будет применена к каждой группе значений `values`, сгруппированным по значениям `index` и `columns`. Значения этой функции и есть значения сводной таблицы. Если передается список функций, то сводная таблица имеет иерархические имена колонок, верхние значения которых — имена функций;\n", "* `fill_value` — значения для замены пропусков;\n", "* `dropna` — не включать столбцы, которые состоят только из `NaN`;\n", "* `margins` — добавляет результирующий столбец/строку;\n", "* `margins_name` — имя результирующего столбец/строку.\n", "\n", "В примере выше:\n", "\n", "`pd.pivot_table(df, index='врач', columns='диагноз', margins=True)`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-------------\n", "\n", "#### 4.3 Примеры\n", "\n", "Создадим таблицу для примера" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
СпециальностьВрачДиагнозДозаПродолжительность
0ВетеринарАндрейПростуда51
1ВетеринарСергейПростуда52
2ПсихологИринаПростуда55
3ПсихологАндрейВолнения35
4ВетеринарСергейВолнения14
5ВетеринарИринаПростуда53
6ПсихологАндрейПростуда22
7ПсихологСергейПростуда41
8ВетеринарИринаПростуда55
9ВетеринарАндрейВолнения24
10ПсихологСергейВолнения34
11ПсихологИринаПростуда35
12ВетеринарАндрейПростуда35
13ВетеринарСергейПростуда54
14ПсихологИринаПростуда42
15ПсихологАндрейВолнения55
16ВетеринарСергейВолнения44
17ВетеринарИринаПростуда12
18ПсихологАндрейПростуда41
19ПсихологСергейПростуда34
20ВетеринарИринаПростуда25
21ВетеринарАндрейВолнения55
22ПсихологСергейВолнения21
23ПсихологИринаПростуда34
\n", "
" ], "text/plain": [ " Специальность Врач Диагноз Доза Продолжительность\n", "0 Ветеринар Андрей Простуда 5 1\n", "1 Ветеринар Сергей Простуда 5 2\n", "2 Психолог Ирина Простуда 5 5\n", "3 Психолог Андрей Волнения 3 5\n", "4 Ветеринар Сергей Волнения 1 4\n", "5 Ветеринар Ирина Простуда 5 3\n", "6 Психолог Андрей Простуда 2 2\n", "7 Психолог Сергей Простуда 4 1\n", "8 Ветеринар Ирина Простуда 5 5\n", "9 Ветеринар Андрей Волнения 2 4\n", "10 Психолог Сергей Волнения 3 4\n", "11 Психолог Ирина Простуда 3 5\n", "12 Ветеринар Андрей Простуда 3 5\n", "13 Ветеринар Сергей Простуда 5 4\n", "14 Психолог Ирина Простуда 4 2\n", "15 Психолог Андрей Волнения 5 5\n", "16 Ветеринар Сергей Волнения 4 4\n", "17 Ветеринар Ирина Простуда 1 2\n", "18 Психолог Андрей Простуда 4 1\n", "19 Психолог Сергей Простуда 3 4\n", "20 Ветеринар Ирина Простуда 2 5\n", "21 Ветеринар Андрей Волнения 5 5\n", "22 Психолог Сергей Волнения 2 1\n", "23 Психолог Ирина Простуда 3 4" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.DataFrame({\n", " 'Специальность' : ['Ветеринар', 'Ветеринар', \n", " 'Психолог', 'Психолог'] * 6,\n", " 'Врач' : ['Андрей', 'Сергей', 'Ирина'] * 8,\n", " 'Диагноз' : ['Простуда', 'Простуда', 'Простуда', \n", " 'Волнения', 'Волнения', 'Простуда'] * 4,\n", " 'Доза' : sps.randint(low=1, high=6).rvs(size=24),\n", " 'Продолжительность' : sps.randint(low=1, high=6).rvs(size=24)\n", "})\n", "\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Посчитаем, сколько раз какой врач ставил каждый из диагнозов, а также суммы по строкам и столбцам" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ДиагнозВолненияПростудаAll
Врач
Андрей448
Ирина088
Сергей448
All81624
\n", "
" ], "text/plain": [ "Диагноз Волнения Простуда All\n", "Врач \n", "Андрей 4 4 8\n", "Ирина 0 8 8\n", "Сергей 4 4 8\n", "All 8 16 24" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.crosstab(df['Врач'], df['Диагноз'], margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Посчитаем, какую среднюю дозу какой врач назначал по каждому из диагнозов" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ДиагнозВолненияПростуда
Врач
Андрей3.753.50
ИринаNaN3.50
Сергей2.504.25
\n", "
" ], "text/plain": [ "Диагноз Волнения Простуда\n", "Врач \n", "Андрей 3.75 3.50\n", "Ирина NaN 3.50\n", "Сергей 2.50 4.25" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.crosstab(df['Врач'], df['Диагноз'], \n", " values=df['Доза'], aggfunc=np.mean)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Простейший вариант сводной таблицы — среднее в группах, определяемых столбцом. Посчитаем средние по каждому врачу" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ДозаПродолжительность
Врач
Андрей3.6253.500
Ирина3.5003.875
Сергей3.3753.000
\n", "
" ], "text/plain": [ " Доза Продолжительность\n", "Врач \n", "Андрей 3.625 3.500\n", "Ирина 3.500 3.875\n", "Сергей 3.375 3.000" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(df, index=['Врач'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Посчитаем, сколько раз врач и в какой специальности ставил тот или иной диагноз" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ДиагнозВолненияПростуда
СпециальностьВрач
ВетеринарАндрей7.08.0
ИринаNaN13.0
Сергей5.010.0
ПсихологАндрей8.06.0
ИринаNaN15.0
Сергей5.07.0
\n", "
" ], "text/plain": [ "Диагноз Волнения Простуда\n", "Специальность Врач \n", "Ветеринар Андрей 7.0 8.0\n", " Ирина NaN 13.0\n", " Сергей 5.0 10.0\n", "Психолог Андрей 8.0 6.0\n", " Ирина NaN 15.0\n", " Сергей 5.0 7.0" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(df, \n", " values='Доза', \n", " index=['Специальность', 'Врач'],\n", " columns=['Диагноз'], \n", " aggfunc=np.sum)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Добавим строчку, являющейся суммой столбцов, и столбец, являющийся суммой строк" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ДиагнозВолненияПростудаAll
СпециальностьВрач
ВетеринарАндрей7.08.015
ИринаNaN13.013
Сергей5.010.015
ПсихологАндрей8.06.014
ИринаNaN15.015
Сергей5.07.012
All25.059.084
\n", "
" ], "text/plain": [ "Диагноз Волнения Простуда All\n", "Специальность Врач \n", "Ветеринар Андрей 7.0 8.0 15\n", " Ирина NaN 13.0 13\n", " Сергей 5.0 10.0 15\n", "Психолог Андрей 8.0 6.0 14\n", " Ирина NaN 15.0 15\n", " Сергей 5.0 7.0 12\n", "All 25.0 59.0 84" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(df, \n", " values='Доза', \n", " index=['Специальность', 'Врач'],\n", " columns=['Диагноз'],\n", " aggfunc=np.sum, \n", " margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Применим несколько функций и несколько столбцов со значениями" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
aminmeanamax
ДозаПродолжительностьДозаПродолжительностьДозаПродолжительность
ДиагнозВолненияПростудаAllВолненияПростудаAllВолненияПростудаAllВолненияПростудаAllВолненияПростудаAllВолненияПростудаAll
СпециальностьВрач
ВетеринарАндрей2.03.024.01.013.5004.00003.754.53.00003.7500005.05.055.05.05
ИринаNaN1.01NaN2.02NaN3.25003.25NaN3.75003.750000NaN5.05NaN5.05
Сергей1.05.014.02.022.5005.00003.754.03.00003.5000004.05.054.04.04
ПсихологАндрей3.02.025.01.014.0003.00003.505.01.50003.2500005.04.055.02.05
ИринаNaN3.03NaN2.02NaN3.75003.75NaN4.00004.000000NaN5.05NaN5.05
Сергей2.03.021.01.012.5003.50003.002.52.50002.5000003.04.044.04.04
All1.01.011.01.013.1253.68753.504.03.18753.4583335.05.055.05.05
\n", "
" ], "text/plain": [ " amin \\\n", " Доза Продолжительность \n", "Диагноз Волнения Простуда All Волнения Простуда All \n", "Специальность Врач \n", "Ветеринар Андрей 2.0 3.0 2 4.0 1.0 1 \n", " Ирина NaN 1.0 1 NaN 2.0 2 \n", " Сергей 1.0 5.0 1 4.0 2.0 2 \n", "Психолог Андрей 3.0 2.0 2 5.0 1.0 1 \n", " Ирина NaN 3.0 3 NaN 2.0 2 \n", " Сергей 2.0 3.0 2 1.0 1.0 1 \n", "All 1.0 1.0 1 1.0 1.0 1 \n", "\n", " mean \\\n", " Доза Продолжительность \n", "Диагноз Волнения Простуда All Волнения Простуда \n", "Специальность Врач \n", "Ветеринар Андрей 3.500 4.0000 3.75 4.5 3.0000 \n", " Ирина NaN 3.2500 3.25 NaN 3.7500 \n", " Сергей 2.500 5.0000 3.75 4.0 3.0000 \n", "Психолог Андрей 4.000 3.0000 3.50 5.0 1.5000 \n", " Ирина NaN 3.7500 3.75 NaN 4.0000 \n", " Сергей 2.500 3.5000 3.00 2.5 2.5000 \n", "All 3.125 3.6875 3.50 4.0 3.1875 \n", "\n", " amax \\\n", " Доза Продолжительность \n", "Диагноз All Волнения Простуда All Волнения \n", "Специальность Врач \n", "Ветеринар Андрей 3.750000 5.0 5.0 5 5.0 \n", " Ирина 3.750000 NaN 5.0 5 NaN \n", " Сергей 3.500000 4.0 5.0 5 4.0 \n", "Психолог Андрей 3.250000 5.0 4.0 5 5.0 \n", " Ирина 4.000000 NaN 5.0 5 NaN \n", " Сергей 2.500000 3.0 4.0 4 4.0 \n", "All 3.458333 5.0 5.0 5 5.0 \n", "\n", " \n", " \n", "Диагноз Простуда All \n", "Специальность Врач \n", "Ветеринар Андрей 5.0 5 \n", " Ирина 5.0 5 \n", " Сергей 4.0 4 \n", "Психолог Андрей 2.0 5 \n", " Ирина 5.0 5 \n", " Сергей 4.0 4 \n", "All 5.0 5 " ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(df, \n", " values=['Доза', 'Продолжительность'], \n", " index=['Специальность', 'Врач'],\n", " columns=['Диагноз'], \n", " aggfunc=[np.min, np.mean, np.max], \n", " margins=True)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 2 }