Python для анализа данных¶
Перед изучением убедитесь, что вы достаточно хорошо ознакомились с первой частью нашего материала про pandas.
Операции в pandas¶
import numpy as np
import pandas as pd
import scipy.stats as sps
1. Простые операции¶
Сгенерируем случайные числа и представим их в виде DataFrame
.
df = pd.DataFrame(sps.norm.rvs(size=(10, 4)),
columns=['A', 'B', 'C', 'D'])
df
A | B | C | D | |
---|---|---|---|---|
0 | -1.345702 | 1.583271 | 0.480914 | -0.053891 |
1 | -1.513222 | 0.389656 | 0.448918 | -0.265700 |
2 | 0.817235 | -1.573969 | -0.080860 | 2.160590 |
3 | -0.773110 | 0.569715 | 0.078057 | -0.215249 |
4 | -0.178111 | 0.286518 | 0.035825 | 0.805861 |
5 | 0.849732 | -0.182298 | -0.224015 | 0.208410 |
6 | -1.701552 | -0.586663 | -1.313644 | 0.470541 |
7 | -0.373508 | -0.813824 | -0.251265 | -0.834696 |
8 | -0.745802 | -0.160359 | -0.934386 | -0.358681 |
9 | -1.116177 | 0.229204 | -2.352976 | -0.348601 |
Выведем описательные статистики по столбцам — количество значений, среднее, стандартное отклонение (корень из дисперсии), минимум, квантили, максимум.
df.describe()
A | B | C | D | |
---|---|---|---|---|
count | 10.000000 | 10.000000 | 10.000000 | 10.000000 |
mean | -0.608022 | -0.025875 | -0.411343 | 0.156858 |
std | 0.898149 | 0.859838 | 0.882121 | 0.843477 |
min | -1.701552 | -1.573969 | -2.352976 | -0.834696 |
25% | -1.288321 | -0.485572 | -0.763606 | -0.327876 |
50% | -0.759456 | 0.034423 | -0.152438 | -0.134570 |
75% | -0.226960 | 0.363871 | 0.067499 | 0.405008 |
max | 0.849732 | 1.583271 | 0.480914 | 2.160590 |
Среднее по столбцам.
df.mean()
A -0.608022 B -0.025875 C -0.411343 D 0.156858 dtype: float64
Оценка матрицы корреляций значений в столбцах.
df.corr()
A | B | C | D | |
---|---|---|---|---|
A | 1.000000 | -0.524331 | 0.210587 | 0.522391 |
B | -0.524331 | 1.000000 | 0.240015 | -0.474598 |
C | 0.210587 | 0.240015 | 1.000000 | 0.154964 |
D | 0.522391 | -0.474598 | 0.154964 | 1.000000 |
Применение функции к данным. Для примера посчитаем разброс значений — разница максимума и минимума.
df.apply(lambda x: x.max() - x.min())
A 2.551284 B 3.157239 C 2.833890 D 2.995285 dtype: float64
2. Объединение таблиц¶
2.1 Функция df.append
¶
Добавление строк в виде таблицы other
в таблицу df
. При наличии у новых строк колонок, которых нет в таблице, они добавляются в таблицу.
df.append(other, ignore_index=False, verify_integrity=False, sort=None)
df
— таблица;other
— добавляемые строки в виде таблицы;ignore_index
— сохранить индексы или определить их как $0, ..., n-1$;verify_integrity
— еслиTrue
, то создает исключение в случае повторения индексов;sort
— сортировать ли колонки, если они (или их порядок) различаются.
Создадим новую таблицу из первых четырех строк таблицы df
. В новую таблицу добавим колонку flag
, в которую запишем условие, что число в столбце D положительно. Затем добавим строки из новой таблицы к старой. Полученная таблица содержит пропуски, которые отмечены как NaN
.
other = df[:4].copy() # Полное копирование
other['flag'] = other['D'] > 0
other['D'] = other['D'] ** 2
df.append(other, ignore_index=True, sort=False)
A | B | C | D | flag | |
---|---|---|---|---|---|
0 | -1.345702 | 1.583271 | 0.480914 | -0.053891 | NaN |
1 | -1.513222 | 0.389656 | 0.448918 | -0.265700 | NaN |
2 | 0.817235 | -1.573969 | -0.080860 | 2.160590 | NaN |
3 | -0.773110 | 0.569715 | 0.078057 | -0.215249 | NaN |
4 | -0.178111 | 0.286518 | 0.035825 | 0.805861 | NaN |
5 | 0.849732 | -0.182298 | -0.224015 | 0.208410 | NaN |
6 | -1.701552 | -0.586663 | -1.313644 | 0.470541 | NaN |
7 | -0.373508 | -0.813824 | -0.251265 | -0.834696 | NaN |
8 | -0.745802 | -0.160359 | -0.934386 | -0.358681 | NaN |
9 | -1.116177 | 0.229204 | -2.352976 | -0.348601 | NaN |
10 | -1.345702 | 1.583271 | 0.480914 | 0.002904 | False |
11 | -1.513222 | 0.389656 | 0.448918 | 0.070597 | False |
12 | 0.817235 | -1.573969 | -0.080860 | 4.668147 | True |
13 | -0.773110 | 0.569715 | 0.078057 | 0.046332 | False |
2.2 Функция pd.concat
¶
Соединение таблиц вдоль выбранной оси.
pd.concat(objs, axis=0, join='outer', ignore_index=False, copy=True, ...)
objs
— объединяемые таблицы;axis
: {0
или'index'
,1
или'columns'
} — ось индексов или ось колонок, иными словами соединение по вертикали или по горизонтали;join
: {'inner'
,'outer'
} — тип объединения — пересечение или объединение индексов/колонок;ignore_index
— сохранить индексы или определить и как $0, ..., n-1$;copy
— копировать данные или нет.
Простой пример соединения таблиц:
pd.concat([df[:5], df[5:]])
A | B | C | D | |
---|---|---|---|---|
0 | -1.345702 | 1.583271 | 0.480914 | -0.053891 |
1 | -1.513222 | 0.389656 | 0.448918 | -0.265700 |
2 | 0.817235 | -1.573969 | -0.080860 | 2.160590 |
3 | -0.773110 | 0.569715 | 0.078057 | -0.215249 |
4 | -0.178111 | 0.286518 | 0.035825 | 0.805861 |
5 | 0.849732 | -0.182298 | -0.224015 | 0.208410 |
6 | -1.701552 | -0.586663 | -1.313644 | 0.470541 |
7 | -0.373508 | -0.813824 | -0.251265 | -0.834696 |
8 | -0.745802 | -0.160359 | -0.934386 | -0.358681 |
9 | -1.116177 | 0.229204 | -2.352976 | -0.348601 |
2.3 Функции pd.merge
и df.join
¶
Слияние таблиц по вертикали путем выполнения операций слияния баз данных в стиле SQL.
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, suffixes=('_x', '_y'), ...)
left
иright
— объединяемые таблицы.how
— тип объединения:left
— только по ключам из левой таблицы == SQL left outer join;right
— только по ключам из правой таблицы == SQL right outer join;outer
— по объединению ключей == SQL full outer join;inner
— по пересечению ключей == SQL inner join.
on
— имя (или имена) колонок, по которым будет производиться объединение (т.е. ключи). Если их несколько, то нужно передать список имен. Имена колонок в таблице должны совпадать.left_on
иright_on
— аналогичноon
для случая, когда в таблицах различаются имена колонок, соответствующие ключам.left_index
иright_index
— использовать ли индексы в качестве ключей.suffixes
— суффиксы, которые будут добавлены к тем колонкам, имена которых повторяются.
Пример. Опция how=left, left_on='A', right_on='B'
соответствует взятию всех строк из таблицы left
, а из таблицы right
берутся те строки, в которых значения в колонке A
таблицы left
совпадает со значением колонки B
таблицы right
. Если в одной из таблиц таких значений несколько, то строки другой таблицы дублируются. Если в таблице right
каких-то значений нет, то в результирующей таблице будут пропуски.
df.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
df
— основная таблица. В качестве ключей используется индекс.other
— другая таблица.on
— колонка(-и) вother
, соответствующая ключам, по ним происходит объединение. ЕслиNone
, то используется индекс.how
— тип объединения (см.pd.merge
).lsuffix
иrsuffix
— суффиксы, которые будут добавлены к тем колонкам, имена которых повторяются.
left = pd.DataFrame({'key': ['A', 'A'],
'lval': [1, 2]})
right = pd.DataFrame({'key': ['A', 'A'],
'rval': [4, 5]})
left
key | lval | |
---|---|---|
0 | A | 1 |
1 | A | 2 |
right
key | rval | |
---|---|---|
0 | A | 4 |
1 | A | 5 |
В результате объединения получаем 4 строки — для каждой строки из левой таблицы есть две строки из правой таблицы с таким же ключом.
pd.merge(left, right, on='key')
key | lval | rval | |
---|---|---|---|
0 | A | 1 | 4 |
1 | A | 1 | 5 |
2 | A | 2 | 4 |
3 | A | 2 | 5 |
Пример 2.¶
В таблицах ключи не повторяются.
left = pd.DataFrame({'key': ['A', 'B'],
'lval': [1, 2]})
right = pd.DataFrame({'key': ['A', 'B'],
'rval': [4, 5]})
left
key | lval | |
---|---|---|
0 | A | 1 |
1 | B | 2 |
right
key | rval | |
---|---|---|
0 | A | 4 |
1 | B | 5 |
В результате объединения получаем 2 строки — для каждой строки из левой таблицы есть только одна строка из правой таблицы с таким же ключом.
pd.merge(left, right, on='key')
key | lval | rval | |
---|---|---|---|
0 | A | 1 | 4 |
1 | B | 2 | 5 |
Пример 3.¶
Посмотрим на различные типы объединения. Создадим и напечатаем две таблицы.
left = pd.DataFrame({'lkey': ['A', 'B', 'C', 'A'],
'value': range(4)})
right = pd.DataFrame({'rkey': ['A', 'B', 'D', 'B'],
'value': range(4, 8)})
left
lkey | value | |
---|---|---|
0 | A | 0 |
1 | B | 1 |
2 | C | 2 |
3 | A | 3 |
right
rkey | value | |
---|---|---|
0 | A | 4 |
1 | B | 5 |
2 | D | 6 |
3 | B | 7 |
Внешнее слияние — используются ключи из объединения списков ключей. Иначе говоря, используются ключи, которые есть хотя бы в одной из таблиц. Если в другой таблице таких ключей нет, то ставятся пропуски.
pd.merge(left, right,
left_on='lkey', right_on='rkey', how='outer')
lkey | value_x | rkey | value_y | |
---|---|---|---|---|
0 | A | 0.0 | A | 4.0 |
1 | A | 3.0 | A | 4.0 |
2 | B | 1.0 | B | 5.0 |
3 | B | 1.0 | B | 7.0 |
4 | C | 2.0 | NaN | NaN |
5 | NaN | NaN | D | 6.0 |
Внутреннее слияние — используются ключи из пересечения списков ключей. Иначе говоря, используются ключи, которые присутствуют в обеих таблицах.
pd.merge(left, right,
left_on='lkey', right_on='rkey', how='inner')
lkey | value_x | rkey | value_y | |
---|---|---|---|---|
0 | A | 0 | A | 4 |
1 | A | 3 | A | 4 |
2 | B | 1 | B | 5 |
3 | B | 1 | B | 7 |
Объединение по ключам левой таблицы. Не используются ключи, которые есть в правой таблице, но которых нет в левой. Если в правой таблице каких-то ключей нет, то ставятся пропуски.
pd.merge(left, right,
left_on='lkey', right_on='rkey', how='left')
lkey | value_x | rkey | value_y | |
---|---|---|---|---|
0 | A | 0 | A | 4.0 |
1 | B | 1 | B | 5.0 |
2 | B | 1 | B | 7.0 |
3 | C | 2 | NaN | NaN |
4 | A | 3 | A | 4.0 |
Объединение по ключам правой таблицы. Не используются ключи, которые есть в левой таблице, но которых нет в правой. Если в левой таблице каких-то ключей нет, то ставятся пропуски.
pd.merge(left, right,
left_on='lkey', right_on='rkey', how='right')
lkey | value_x | rkey | value_y | |
---|---|---|---|---|
0 | A | 0.0 | A | 4 |
1 | A | 3.0 | A | 4 |
2 | B | 1.0 | B | 5 |
3 | B | 1.0 | B | 7 |
4 | NaN | NaN | D | 6 |
Выполним внутреннее объединение и установим ключ качестве индекса.
pd.merge(left, right,
left_on='lkey', right_on='rkey', how='inner') \
.set_index('lkey')[['value_x', 'value_y']]
value_x | value_y | |
---|---|---|
lkey | ||
A | 0 | 4 |
A | 3 | 4 |
B | 1 | 5 |
B | 1 | 7 |
Ту же операцию можно выполнить с помощью join
.
left.set_index('lkey') \
.join(right.set_index('rkey'), rsuffix='_r', how='inner')
value | value_r | |
---|---|---|
A | 0 | 4 |
A | 3 | 4 |
B | 1 | 5 |
B | 1 | 7 |
3. Группировка¶
Часто на практике необходимо вычислять среднее по каким-либо категориям или группам в данных. Группа может определяться, например, столбцом в таблице, у которого не так много значений. Мы хотели бы для каждого такого значения посчитать среднее значение другой колонки данных в этой группе.
Этапы группировки данных:
- разбиение данных на группы по некоторым критериям;
- применение функции отдельно к каждой группе;
- комбинирование результата в структуру данных.
Группировка выполняется функцией:
df.groupby(by=None, axis=0, level=None, sort=True, ...)
df
— таблица, данные которой должны быть сгруппированы;by
— задает принцип группировки. Чаще всего это имя столбца, по которому нужно сгруппировать. Может так же быть функцией;axis
— ось (0 = группировать строки, 1 = группировать столбцы);level
— если ось представлена мультииндексом, то указывает на уровень мультииндекса;sort
— сортировка результата по индексу.
Результатом группировки является объект, состоящий из пар (имя группы, подтаблица). Имя группы соответствует значению, по которому произведена группировка. К объекту-результату группировки применимы, например, следующие операции:
for name, group in groupped: ...
— цикл по группам;get_group(name)
— получить таблицу, соответствующую группе с именемname
;groups
— получить все группы в виде словаря имя-подтаблица;count()
— количество значений в группах, исключая пропуски;size()
— размер групп;sum()
,max()
,min()
;mean()
,median()
,var()
,std()
,corr()
,quantile(q)
;describe()
— вывод описательных статистик;aggregate(func)
— применение функции (или списка функций)func
к группам.
Создадим таблицу для примера.
df = pd.DataFrame({
'Животное' : ['Котик', 'Песик', 'Котик', 'Песик',
'Котик', 'Песик', 'Котик', 'Песик'],
'Цвет шерсти' : ['белый', 'белый', 'коричневый', 'черный',
'коричневый', 'коричневый', 'белый', 'черный'],
'Рост' : sps.gamma(a=12, scale=3).rvs(size=8),
'Длина хвостика' : sps.gamma(a=10).rvs(size=8)
})
df
Животное | Цвет шерсти | Рост | Длина хвостика | |
---|---|---|---|---|
0 | Котик | белый | 33.756262 | 8.498897 |
1 | Песик | белый | 35.634198 | 7.056738 |
2 | Котик | коричневый | 30.892027 | 17.375188 |
3 | Песик | черный | 23.272997 | 4.179033 |
4 | Котик | коричневый | 33.002035 | 12.200925 |
5 | Песик | коричневый | 41.045798 | 14.026990 |
6 | Котик | белый | 42.275420 | 7.053550 |
7 | Песик | черный | 31.761933 | 10.652498 |
Пример 1.¶
Если все котики встанут друг на друга, то какой их суммарный рост? А у песиков? А какова суммарная длина хвостиков у котиков и у песиков?
Группировка по одной колонке и последующее применение операции суммирования:
df.groupby('Животное').sum()
Рост | Длина хвостика | |
---|---|---|
Животное | ||
Котик | 139.925743 | 45.12856 |
Песик | 131.714925 | 35.91526 |
Посчитаем описательные статистики для каждого животного.
df.groupby('Животное').describe()
Рост | Длина хвостика | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | count | mean | std | min | 25% | 50% | 75% | max | |
Животное | ||||||||||||||||
Котик | 4.0 | 34.981436 | 5.011472 | 30.892027 | 32.474533 | 33.379148 | 35.886051 | 42.275420 | 4.0 | 11.282140 | 4.604231 | 7.053550 | 8.137560 | 10.349911 | 13.494491 | 17.375188 |
Песик | 4.0 | 32.928731 | 7.478880 | 23.272997 | 29.639699 | 33.698065 | 36.987098 | 41.045798 | 4.0 | 8.978815 | 4.282428 | 4.179033 | 6.337312 | 8.854618 | 11.496121 | 14.026990 |
Пример 2.¶
Теперь предположим, что котики и песики встают только на представителей своего вида и своего цвета шерсти. Что тогда будет?
Группировка по двум колонкам и последующее применение операции суммирования.
df.groupby(['Животное', 'Цвет шерсти']).sum()
Рост | Длина хвостика | ||
---|---|---|---|
Животное | Цвет шерсти | ||
Котик | белый | 76.031682 | 15.552447 |
коричневый | 63.894061 | 29.576113 | |
Песик | белый | 35.634198 | 7.056738 |
коричневый | 41.045798 | 14.026990 | |
черный | 55.034930 | 14.831531 |
Полученная таблица имеет мультииндекс.
df.groupby(['Животное', 'Цвет шерсти']).sum().index
MultiIndex([('Котик', 'белый'), ('Котик', 'коричневый'), ('Песик', 'белый'), ('Песик', 'коричневый'), ('Песик', 'черный')], names=['Животное', 'Цвет шерсти'])
4. Таблицы сопряженности (Crosstab) и сводные таблицы (Pivot table)¶
Задача. В медицинской клинике информацию о приемах записывают в таблицу со следующими полями:
- время приема,
- врач,
- пациент,
- поставленный диагноз,
- назначение,
- другие поля.
Требуется посчитать, сколько раз за предыдущий месяц каждый врач ставил какой-либо диагноз. Результаты представить в виде таблицы, в которой посчитать также суммы по строкам и столбцам, т.е. сколько врач сделал приемов за месяц и сколько раз конкретный диагноз поставлен всеми врачами.
Как решать?
Способ 1
- Группировка по врачам.
- Для каждого врача группировка по диагнозам.
- В каждой группе вычисление суммы.
- Соединение в одну таблицу.
- Вычисление суммы по столбцам и по строкам.
Можете прикинуть количество строк кода и время работы 😁
Способ 2
- Создать пустую таблицу.
- Циклом 🤣 по всем записям исходной таблицы считать суммы.
- Вычисление суммы по столбцам и по строкам.
И снова можете прикинуть количество строк кода и время работы 😁
Способ 3
Применить умную функцию из pandas, которая сделает все сама!
4.1 Функция pd.crosstab
¶
Эксель-подобные таблицы сопряженности
pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, margins_name='All', dropna=True, normalize=False)
index
— значения для группировки по строкам;columns
— значения для группировки по столбцам;values
— агрегируемый столбец (или столбцы), его значения непосредственно определяют значения таблицы сопряженности;aggfunc
— функция, которая будет применена к каждой группе значенийvalues
, сгруппированным по значениямindex
иcolumns
. Значения этой функции и есть значения сводной таблицы;rownames
иcolnames
— имена строк и столбцов таблицы сопряженности;margins
— добавляет результирующий столбец/строку;margins_name
— имя результирующего столбец/строку;dropna
— не включать столбцы, которые состоят только изNaN
;normalize
:boolean
, {'all'
,'index'
,'columns'
} — нормировка всей таблицы (или только по строкам/столбцам).
В примере выше:
pd.crosstab(df['Врач'], df['Диагноз'], margins=True)
4.2 Функция pd.pivot_table
¶
Эксель-подобные сводные таблицы
pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
data
— исходная таблица;values
— аггригируемый столбец, его значения непосредственно определяют значения сводной таблицы;index
— ключи для группировки, относятся к индексам сводной таблицы;columns
— ключи для группировки, относятся к столбцам сводной таблицы;aggfunc
— функция, которая будет применена к каждой группе значенийvalues
, сгруппированным по значениямindex
иcolumns
. Значения этой функции и есть значения сводной таблицы. Если передается список функций, то сводная таблица имеет иерархические имена колонок, верхние значения которых — имена функций;fill_value
— значения для замены пропусков;dropna
— не включать столбцы, которые состоят только изNaN
;margins
— добавляет результирующий столбец/строку;margins_name
— имя результирующего столбец/строку.
В примере выше:
pd.pivot_table(df, index='врач', columns='диагноз', margins=True)
df = pd.DataFrame({
'Специальность' : ['Ветеринар', 'Ветеринар',
'Психолог', 'Психолог'] * 6,
'Врач' : ['Андрей', 'Сергей', 'Ирина'] * 8,
'Диагноз' : ['Простуда', 'Простуда', 'Простуда',
'Волнения', 'Волнения', 'Простуда'] * 4,
'Доза' : sps.randint(low=1, high=6).rvs(size=24),
'Продолжительность' : sps.randint(low=1, high=6).rvs(size=24)
})
df
Специальность | Врач | Диагноз | Доза | Продолжительность | |
---|---|---|---|---|---|
0 | Ветеринар | Андрей | Простуда | 5 | 1 |
1 | Ветеринар | Сергей | Простуда | 5 | 2 |
2 | Психолог | Ирина | Простуда | 5 | 5 |
3 | Психолог | Андрей | Волнения | 3 | 5 |
4 | Ветеринар | Сергей | Волнения | 1 | 4 |
5 | Ветеринар | Ирина | Простуда | 5 | 3 |
6 | Психолог | Андрей | Простуда | 2 | 2 |
7 | Психолог | Сергей | Простуда | 4 | 1 |
8 | Ветеринар | Ирина | Простуда | 5 | 5 |
9 | Ветеринар | Андрей | Волнения | 2 | 4 |
10 | Психолог | Сергей | Волнения | 3 | 4 |
11 | Психолог | Ирина | Простуда | 3 | 5 |
12 | Ветеринар | Андрей | Простуда | 3 | 5 |
13 | Ветеринар | Сергей | Простуда | 5 | 4 |
14 | Психолог | Ирина | Простуда | 4 | 2 |
15 | Психолог | Андрей | Волнения | 5 | 5 |
16 | Ветеринар | Сергей | Волнения | 4 | 4 |
17 | Ветеринар | Ирина | Простуда | 1 | 2 |
18 | Психолог | Андрей | Простуда | 4 | 1 |
19 | Психолог | Сергей | Простуда | 3 | 4 |
20 | Ветеринар | Ирина | Простуда | 2 | 5 |
21 | Ветеринар | Андрей | Волнения | 5 | 5 |
22 | Психолог | Сергей | Волнения | 2 | 1 |
23 | Психолог | Ирина | Простуда | 3 | 4 |
Посчитаем, сколько раз какой врач ставил каждый из диагнозов, а также суммы по строкам и столбцам.
pd.crosstab(df['Врач'], df['Диагноз'], margins=True)
Диагноз | Волнения | Простуда | All |
---|---|---|---|
Врач | |||
Андрей | 4 | 4 | 8 |
Ирина | 0 | 8 | 8 |
Сергей | 4 | 4 | 8 |
All | 8 | 16 | 24 |
Посчитаем, какую среднюю дозу какой врач назначал по каждому из диагнозов.
pd.crosstab(df['Врач'], df['Диагноз'],
values=df['Доза'], aggfunc=np.mean)
Диагноз | Волнения | Простуда |
---|---|---|
Врач | ||
Андрей | 3.75 | 3.50 |
Ирина | NaN | 3.50 |
Сергей | 2.50 | 4.25 |
Простейший вариант сводной таблицы — среднее в группах, определяемых столбцом. Посчитаем средние по каждому врачу.
pd.pivot_table(df, index=['Врач'])
Доза | Продолжительность | |
---|---|---|
Врач | ||
Андрей | 3.625 | 3.500 |
Ирина | 3.500 | 3.875 |
Сергей | 3.375 | 3.000 |
Посчитаем, сколько раз врач и в какой специальности ставил тот или иной диагноз.
pd.pivot_table(df,
values='Доза',
index=['Специальность', 'Врач'],
columns=['Диагноз'],
aggfunc=np.sum)
Диагноз | Волнения | Простуда | |
---|---|---|---|
Специальность | Врач | ||
Ветеринар | Андрей | 7.0 | 8.0 |
Ирина | NaN | 13.0 | |
Сергей | 5.0 | 10.0 | |
Психолог | Андрей | 8.0 | 6.0 |
Ирина | NaN | 15.0 | |
Сергей | 5.0 | 7.0 |
Добавим строчку, являющейся суммой столбцов, и столбец, являющийся суммой строк.
pd.pivot_table(df,
values='Доза',
index=['Специальность', 'Врач'],
columns=['Диагноз'],
aggfunc=np.sum,
margins=True)
Диагноз | Волнения | Простуда | All | |
---|---|---|---|---|
Специальность | Врач | |||
Ветеринар | Андрей | 7.0 | 8.0 | 15 |
Ирина | NaN | 13.0 | 13 | |
Сергей | 5.0 | 10.0 | 15 | |
Психолог | Андрей | 8.0 | 6.0 | 14 |
Ирина | NaN | 15.0 | 15 | |
Сергей | 5.0 | 7.0 | 12 | |
All | 25.0 | 59.0 | 84 |
Применим несколько функций и несколько столбцов со значениями.
pd.pivot_table(df,
values=['Доза', 'Продолжительность'],
index=['Специальность', 'Врач'],
columns=['Диагноз'],
aggfunc=[np.min, np.mean, np.max],
margins=True)
amin | mean | amax | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Доза | Продолжительность | Доза | Продолжительность | Доза | Продолжительность | ||||||||||||||
Диагноз | Волнения | Простуда | All | Волнения | Простуда | All | Волнения | Простуда | All | Волнения | Простуда | All | Волнения | Простуда | All | Волнения | Простуда | All | |
Специальность | Врач | ||||||||||||||||||
Ветеринар | Андрей | 2.0 | 3.0 | 2 | 4.0 | 1.0 | 1 | 3.500 | 4.0000 | 3.75 | 4.5 | 3.0000 | 3.750000 | 5.0 | 5.0 | 5 | 5.0 | 5.0 | 5 |
Ирина | NaN | 1.0 | 1 | NaN | 2.0 | 2 | NaN | 3.2500 | 3.25 | NaN | 3.7500 | 3.750000 | NaN | 5.0 | 5 | NaN | 5.0 | 5 | |
Сергей | 1.0 | 5.0 | 1 | 4.0 | 2.0 | 2 | 2.500 | 5.0000 | 3.75 | 4.0 | 3.0000 | 3.500000 | 4.0 | 5.0 | 5 | 4.0 | 4.0 | 4 | |
Психолог | Андрей | 3.0 | 2.0 | 2 | 5.0 | 1.0 | 1 | 4.000 | 3.0000 | 3.50 | 5.0 | 1.5000 | 3.250000 | 5.0 | 4.0 | 5 | 5.0 | 2.0 | 5 |
Ирина | NaN | 3.0 | 3 | NaN | 2.0 | 2 | NaN | 3.7500 | 3.75 | NaN | 4.0000 | 4.000000 | NaN | 5.0 | 5 | NaN | 5.0 | 5 | |
Сергей | 2.0 | 3.0 | 2 | 1.0 | 1.0 | 1 | 2.500 | 3.5000 | 3.00 | 2.5 | 2.5000 | 2.500000 | 3.0 | 4.0 | 4 | 4.0 | 4.0 | 4 | |
All | 1.0 | 1.0 | 1 | 1.0 | 1.0 | 1 | 3.125 | 3.6875 | 3.50 | 4.0 | 3.1875 | 3.458333 | 5.0 | 5.0 | 5 | 5.0 | 5.0 | 5 |