Занятие 3

Лекция 3 и лабораторная 3

1. Pandas

Pandas — это библиотека(пакет) для работы с табличными данными в Python, который имеет огромный функционал.

Цели Pandas:

  1. Импортировать наборы данных из баз данных, электронных таблиц, CSV-файлов.
  2. Очищать наборы данных, например, устраняя пропущенные значения, или же заменять пропущенные значения.
  3. Агрегировать данные, вычислять среднее значение столбцов и строк, корреляцию между ними и т.д.
  4. Визуализировать данные.

Для считывания данных используется функция pd.read_csv. У этой функции много аргументов, которые можно посмотреть в документации. Нам же пока нужен только один: название считываемого файла.

Вот ссылка для скачивания файла

In [5]:
import pandas as pd # импортируем библиотеку
data = pd.read_csv("Housing.csv")
data
Out[5]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
... ... ... ... ... ... ... ... ... ... ... ... ... ...
540 1820000 3000 2 1 1 yes no yes no no 2 no unfurnished
541 1767150 2400 3 1 1 no no no no no 0 no semi-furnished
542 1750000 3620 2 1 1 yes no no no no 0 no unfurnished
543 1750000 2910 3 1 1 no no no no no 0 no furnished
544 1750000 3850 3 1 2 yes no no no no 0 no unfurnished

545 rows × 13 columns

2.1 Просмотр таблицы

Для просмотра таблиц могут быть полезны следующие функции:

  1. head(n) - первые n строк
  2. tail(n) - последние n строк
  3. describe, info - описание данных
  4. shape - размер таблицы
  5. columns - название колонок
In [15]:
data.head(10)
Out[15]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
5 10850000 7500 3 3 1 yes no yes no yes 2 yes semi-furnished
6 10150000 8580 4 3 4 yes no no no yes 2 yes semi-furnished
7 10150000 16200 5 3 2 yes no no no no 0 no unfurnished
8 9870000 8100 4 1 2 yes yes yes no yes 2 yes furnished
9 9800000 5750 3 2 4 yes yes no no yes 1 yes unfurnished
In [73]:
data.tail(10)
Out[73]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
535 2100000 3360 2 1 1 yes no no no no 1 no unfurnished
536 1960000 3420 5 1 2 no no no no no 0 no unfurnished
537 1890000 1700 3 1 2 yes no no no no 0 no unfurnished
538 1890000 3649 2 1 1 yes no no no no 0 no unfurnished
539 1855000 2990 2 1 1 no no no no no 1 no unfurnished
540 1820000 3000 2 1 1 yes no yes no no 2 no unfurnished
541 1767150 2400 3 1 1 no no no no no 0 no semi-furnished
542 1750000 3620 2 1 1 yes no no no no 0 no unfurnished
543 1750000 2910 3 1 1 no no no no no 0 no furnished
544 1750000 3850 3 1 2 yes no no no no 0 no unfurnished
In [74]:
data.shape
Out[74]:
(545, 13)
In [18]:
data.columns
Out[18]:
Index(['price', 'area', 'bedrooms', 'bathrooms', 'stories', 'mainroad',
       'guestroom', 'basement', 'hotwaterheating', 'airconditioning',
       'parking', 'prefarea', 'furnishingstatus'],
      dtype='object')
In [75]:
data.describe()
Out[75]:
price area bedrooms bathrooms stories parking
count 5.450000e+02 545.000000 545.000000 545.000000 545.000000 545.000000
mean 4.766729e+06 5150.541284 2.965138 1.286239 1.805505 0.693578
std 1.870440e+06 2170.141023 0.738064 0.502470 0.867492 0.861586
min 1.750000e+06 1650.000000 1.000000 1.000000 1.000000 0.000000
25% 3.430000e+06 3600.000000 2.000000 1.000000 1.000000 0.000000
50% 4.340000e+06 4600.000000 3.000000 1.000000 2.000000 0.000000
75% 5.740000e+06 6360.000000 3.000000 2.000000 2.000000 1.000000
max 1.330000e+07 16200.000000 6.000000 4.000000 4.000000 3.000000

В Pandas существует два основных варианта синтаксиса для просмотра содержимого столбца:

In [20]:
data.area
Out[20]:
0      7420
1      8960
2      9960
3      7500
4      7420
       ... 
540    3000
541    2400
542    3620
543    2910
544    3850
Name: area, Length: 545, dtype: int64
In [21]:
data['area']
Out[21]:
0      7420
1      8960
2      9960
3      7500
4      7420
       ... 
540    3000
541    2400
542    3620
543    2910
544    3850
Name: area, Length: 545, dtype: int64

Стоит заметить, что таблица и столбцы имеют разный тип:

In [29]:
type(data), type(data.area), type(data['area'])
Out[29]:
(pandas.core.frame.DataFrame,
 pandas.core.series.Series,
 pandas.core.series.Series)

Серия pandas — это одномерный массив, содержащий данные любого типа, включая целые числа, числа с плавающей точкой, строки, булевы значения, объекты Python и т.д. DataFrame состоит из множества серий, которые выступают в качестве столбцов.

Тем не менее, мы можем сделать именно датафрейм из одного столбца следующим образом:

In [30]:
type(data[['area']])
Out[30]:
pandas.core.frame.DataFrame

2.2 Нарезка и извлечение данных в pandas

До этого мы получили датафрейм на основе одного столбца. Для получения более одного столбца можно также указать список имен столбцов внутри квадратных скобок.

In [76]:
data[['area', 'parking', 'guestroom']]
Out[76]:
area parking guestroom
0 7420 2 no
1 8960 3 no
2 9960 2 no
3 7500 3 no
4 7420 2 yes
... ... ... ...
540 3000 2 no
541 2400 0 no
542 3620 0 no
543 2910 0 no
544 3850 0 no

545 rows × 3 columns

Конечно же можно извлекать не только столбцы, но и строки. С помощью loc[] и iloc[] («местоположение» и «целочисленное местоположение»). Важно чётко понимать разницу между loc[] и iloc[].

  • loc[] работает с метками столбцов и строк
  • iloc[] работает с целочисленными позициями нужных элементов
In [77]:
# выведем строки с 5 по 15
data.loc[5:15]
Out[77]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
5 10850000 7500 3 3 1 yes no yes no yes 2 yes semi-furnished
6 10150000 8580 4 3 4 yes no no no yes 2 yes semi-furnished
7 10150000 16200 5 3 2 yes no no no no 0 no unfurnished
8 9870000 8100 4 1 2 yes yes yes no yes 2 yes furnished
9 9800000 5750 3 2 4 yes yes no no yes 1 yes unfurnished
10 9800000 13200 3 1 2 yes no yes no yes 2 yes furnished
11 9681000 6000 4 3 2 yes yes yes yes no 2 no semi-furnished
12 9310000 6550 4 2 2 yes no no no yes 1 yes semi-furnished
13 9240000 3500 4 2 2 yes no no yes no 2 no furnished
14 9240000 7800 3 2 2 yes no no no no 0 yes semi-furnished
15 9100000 6000 4 1 2 yes no yes no no 2 no semi-furnished
In [33]:
# выведем строки с 5 по 15
data.iloc[5:15]
Out[33]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
5 10850000 7500 3 3 1 yes no yes no yes 2 yes semi-furnished
6 10150000 8580 4 3 4 yes no no no yes 2 yes semi-furnished
7 10150000 16200 5 3 2 yes no no no no 0 no unfurnished
8 9870000 8100 4 1 2 yes yes yes no yes 2 yes furnished
9 9800000 5750 3 2 4 yes yes no no yes 1 yes unfurnished
10 9800000 13200 3 1 2 yes no yes no yes 2 yes furnished
11 9681000 6000 4 3 2 yes yes yes yes no 2 no semi-furnished
12 9310000 6550 4 2 2 yes no no no yes 1 yes semi-furnished
13 9240000 3500 4 2 2 yes no no yes no 2 no furnished
14 9240000 7800 3 2 2 yes no no no no 0 yes semi-furnished

2.3 Нарезка данных по условию

До этого момента мы с вами выбирали строки и столбцы определённых номеров. А что если нам будет нужно выбрать строки по какому-то условию?

Здесь нам и поможет .loc.

Выведим строки, содержащие квартиры площадью более 5000.

In [6]:
data.loc[data['area'] > 5000]
Out[6]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
... ... ... ... ... ... ... ... ... ... ... ... ... ...
487 2870000 5400 4 1 2 yes no no no no 0 no unfurnished
488 2852500 5200 4 1 3 yes no no no no 0 no unfurnished
494 2730000 6800 2 1 1 yes no no no no 0 no unfurnished
520 2450000 7700 2 1 1 yes no no no no 0 no unfurnished
531 2233000 5300 3 1 1 no no no no yes 0 yes unfurnished

236 rows × 13 columns

Теперь выведем строки, содержащие квартиры не только с площадью более 5000, но и имеющих три спальни.

In [8]:
data.loc[(data['area'] > 5000) | (data['bedrooms'] == 3)]
Out[8]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
... ... ... ... ... ... ... ... ... ... ... ... ... ...
533 2100000 2400 3 1 2 yes no no no no 0 no unfurnished
537 1890000 1700 3 1 2 yes no no no no 0 no unfurnished
541 1767150 2400 3 1 1 no no no no no 0 no semi-furnished
543 1750000 2910 3 1 1 no no no no no 0 no furnished
544 1750000 3850 3 1 2 yes no no no no 0 no unfurnished

394 rows × 13 columns

Обратите внимание, что мы используем логическое и (&), а не and !

2.4 Агрегация данных с помощью .groupby()

Pandas позволяет агрегировать значения, группируя их по определенным значениям столбцов. Это можно сделать, сочетая метод .groupby() с выбранным вами методом.

Сгруппируем квартиры по числу спален и посчитаем среднее для каждой из групп.

In [82]:
data
Out[82]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished
... ... ... ... ... ... ... ... ... ... ... ... ... ...
540 1820000 3000 2 1 1 yes no yes no no 2 no unfurnished
541 1767150 2400 3 1 1 no no no no no 0 no semi-furnished
542 1750000 3620 2 1 1 yes no no no no 0 no unfurnished
543 1750000 2910 3 1 1 no no no no no 0 no furnished
544 1750000 3850 3 1 2 yes no no no no 0 no unfurnished

545 rows × 13 columns

In [10]:
data.groupby('bedrooms')['price'].min()
Out[10]:
bedrooms
1    2275000
2    1750000
3    1750000
4    2100000
5    1960000
6    3500000
Name: price, dtype: int64

Функция .groupby() позволяет группировать данные более чем по одному столбцу, передавая список имен столбцов, как показано ниже.

In [37]:
data.groupby(['mainroad', 'guestroom']).mean()
Out[37]:
price area bedrooms bathrooms stories parking
mainroad guestroom
no no 3.339295e+06 3631.614286 3.014286 1.200000 1.542857 0.242857
yes 3.995000e+06 3354.714286 2.714286 1.571429 1.571429 0.428571
yes no 4.767740e+06 5264.071429 2.923280 1.267196 1.833333 0.759259
yes 5.932733e+06 5994.777778 3.122222 1.411111 1.911111 0.788889

Вместе с .groupby() можно использовать не только mean, но и:

  • min()
  • max()
  • median()
  • sum()
  • var()

2.5 Создание датафрейма и добавление столбцов

Создать датафрейм можно с помощью pd.DataFrame.

In [38]:
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index = ["first", "second", "third"])
df
Out[38]:
A B
first 1 4
second 2 5
third 3 6

Можем изменить значение конкретного элемента.

In [39]:
df.iloc[0, 0] = -10
df
Out[39]:
A B
first -10 4
second 2 5
third 3 6
In [40]:
df.loc["second", "B"] = -20
df
Out[40]:
A B
first -10 4
second 2 -20
third 3 6

Добавим к таблице новую строку с индексом "next" и заполненную нулями.

In [41]:
df.loc["B"] = 0
df
Out[41]:
A B
first -10 4
second 2 -20
third 3 6
B 0 0

Добавим к таблице новый столбец и заполним его символом "a".

In [42]:
df["C"] = 'a'
df
Out[42]:
A B C
first -10 4 a
second 2 -20 a
third 3 6 a
B 0 0 a

Мы также можем создавать столбец на основе других столбцов. Добавим в таблицу о квартирах новый столбец, содержащий цену квадратного метра квартиры.

In [43]:
data['price_per_area'] = data['price']/data['area']
data.head(10)
Out[43]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus price_per_area
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished 1792.452830
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished 1367.187500
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished 1229.919679
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished 1628.666667
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished 1537.735849
5 10850000 7500 3 3 1 yes no yes no yes 2 yes semi-furnished 1446.666667
6 10150000 8580 4 3 4 yes no no no yes 2 yes semi-furnished 1182.983683
7 10150000 16200 5 3 2 yes no no no no 0 no unfurnished 626.543210
8 9870000 8100 4 1 2 yes yes yes no yes 2 yes furnished 1218.518519
9 9800000 5750 3 2 4 yes yes no no yes 1 yes unfurnished 1704.347826

2.6 value_counts()

Иногда приходится работать с категориальными значениями, и возникает необходимость подсчитать количество наблюдений в столбце для каждой категории. Здесь нам может понадобиться метод .value_counts().

In [12]:
data['price'].value_counts()
Out[12]:
3500000     17
4200000     17
4900000     12
3150000      9
5600000      9
            ..
6580000      1
4319000      1
4375000      1
4382000      1
13300000     1
Name: price, Length: 219, dtype: int64

Как видим, квартир без гостевой комнаты намного больше, чем квартир с ней.

Добавление аргумента normalize возвращает проценты вместо абсолютных значений.

In [45]:
data['guestroom'].value_counts(normalize = True)
Out[45]:
no     0.822018
yes    0.177982
Name: guestroom, dtype: float64

2.7 сортировка

Ну и конечно же мы можем сортировать наши данные по определённому значению.

Отсортируем квартиры по возрастанию цены.

In [46]:
data.sort_values(by=['price'])
Out[46]:
price area bedrooms bathrooms stories mainroad guestroom basement hotwaterheating airconditioning parking prefarea furnishingstatus price_per_area
544 1750000 3850 3 1 2 yes no no no no 0 no unfurnished 454.545455
543 1750000 2910 3 1 1 no no no no no 0 no furnished 601.374570
542 1750000 3620 2 1 1 yes no no no no 0 no unfurnished 483.425414
541 1767150 2400 3 1 1 no no no no no 0 no semi-furnished 736.312500
540 1820000 3000 2 1 1 yes no yes no no 2 no unfurnished 606.666667
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
4 11410000 7420 4 1 2 yes yes yes no yes 2 no furnished 1537.735849
3 12215000 7500 4 2 2 yes no yes no yes 3 yes furnished 1628.666667
2 12250000 9960 3 2 2 yes no yes no no 2 yes semi-furnished 1229.919679
1 12250000 8960 4 4 4 yes no no no yes 3 no furnished 1367.187500
0 13300000 7420 4 2 3 yes no no no yes 2 yes furnished 1792.452830

545 rows × 14 columns

2.8 Матрица корреляции

Создадим матрицу корреляции:

In [13]:
data.corr().round(3)
Out[13]:
price area bedrooms bathrooms stories parking
price 1.000 0.536 0.366 0.518 0.421 0.384
area 0.536 1.000 0.152 0.194 0.084 0.353
bedrooms 0.366 0.152 1.000 0.374 0.409 0.139
bathrooms 0.518 0.194 0.374 1.000 0.326 0.177
stories 0.421 0.084 0.409 0.326 1.000 0.046
parking 0.384 0.353 0.139 0.177 0.046 1.000

Можем создать "тепловую" матрицу корреляции.

In [ ]:

In [15]:
corr = data.corr()
corr.style.background_gradient()
Out[15]:
  price area bedrooms bathrooms stories parking
price 1.000000 0.535997 0.366494 0.517545 0.420712 0.384394
area 0.535997 1.000000 0.151858 0.193820 0.083996 0.352980
bedrooms 0.366494 0.151858 1.000000 0.373930 0.408564 0.139270
bathrooms 0.517545 0.193820 0.373930 1.000000 0.326165 0.177496
stories 0.420712 0.083996 0.408564 0.326165 1.000000 0.045547
parking 0.384394 0.352980 0.139270 0.177496 0.045547 1.000000

На основе построенной матрицы, мы можем говорить о некоторой зависимости(именно линейной) признаков нашей таблицы.

2.9 задачи на Pandas

Вам дан датасет telecom_churn. Решите следующие задачи:

Задача 3. Найдите среднее количество звонков Total day calls для всего датафрейма.

In [ ]:

Задача 4. Найдите среднее количество звонков Total day calls для любого выбранного вами штата.

In [ ]:

Задача 5. Создайте датафрейм, в котором будет среднее количество звонков Total day calls для каждого штата.

In [ ]:

Задача 6. Оставьте в созданном датафрейме строки только с теми штатами, где количество звонков Total day calls больше среднего по исходному датафрейму.

In [ ]:

Задача 7. Создайте датафрейм, в котором будует средние количества звонков Total day calls и Total eve calls для каждого штата.

In [ ]:

Задача 8. Создайте датафрейм, в котором будует средние количества звонков Total day calls и Total eve calls для каждого штата, а также столбец со значениями True и False - ответом на вопрос, больше ли дневных звонков, чем вечерних.

In [ ]:

Задача 9. Найти долю клиентов (отношение их числа к общему количеству клиентов) с international plan и voice mail plan.

In [ ]:

Задача 10. Найти число уникальных значений Area code.

In [ ]:

Задача 11. Вывести DataFrame из 2 столбцов: число звонков в поддержку; число клиентов, звонивших столько раз. Подсказка: используйте функцию агрегации count.

In [ ]:

Задача 12. Вывести DataFrame из 2 столбцов: число звонков в поддержку; доля оттока (Churn). Построить график.

In [ ]:

Задача 13. Найти среднюю длительность международного (intl) звонка.

In [ ]:

Задача 14. Какие звонки дольше - дневные, вечерние или ночные? Ответ привести в формате DataFrame $3*3$: строки - число минут, число звонков, среднее время звонка. Столбцы - день, вечер, ночь

In [ ]:

Задача 15. Сравнить Total day charge для оставшихся и ушедших клиентов.

In [ ]:

Задача 16. Отсортриуйте штаты по Total day charge (по возрастанию).

In [ ]:

Задача 17. Сделайте агрегацию по средним показателям для каждой Area code.

In [ ]:

Задача 18. Выведите датафрейм размера $3*2$: столбцы State, Churn для 100, 102 и 104 строк исходного датафрейма.

In [ ]:

Задача 19. Создайте датафрейм из 2 столбцов, заполненных произвольными числами. Добавьте третий столбец, равный их сумме квадратов.

In [ ]:

Задача 20. Добавьте к созданному датафрейму четвертый столбец, равный среднему значению первых трех, используя функцию mean.

In [ ]: