Занятие 9

Лабораторное занятие 9

Библиотека Pandas

Библиотека pandas построена на базе numpy и предоставляет удобный интерфейс для работы с табличными структурами, которые встречаются почти во всех проектах, связанных с анализом, отчётами и машинным обучением. Название библиотеки происходит от эконометрического термина «панельные данные», используемого для описания многомерных структурированных наборов информации.

В библиотеке pandas определены два основных класса объектов для работы с данными:

  • Series — одномерный массив, способный хранить значения любого типа. По своей структуре напоминает словарь: каждому значению присваивается метка (индекс), которая может быть как числом, так и строкой.

  • DataFrame — двумерная таблица, в которой строки и столбцы имеют имена. Каждый столбец — это объект класса Series, а сами данные удобно организованы для анализа и преобразований.

Работа с пропусками. Объединение датафреймов.

In [ ]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

Создать Series следующим образом:

In [ ]:
s = pd.Series(data, index=index)

data может быть массивом numpy, словарём или скаляром (числом).

index — список меток, по умолчанию это целые числа от 0 до n-1.

In [ ]:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s)

s = pd.Series(np.linspace(0, 1, 5))
print(s)
In [ ]:
s = pd.Series(np.arange(5), index=["a", "b", "c", "d", "e"])
print(s["a"])             # Один элемент
print(s[["a", "d"]])      # Несколько элементов
print(s[1:])              # Срез
print(s + s)              # Поэлементное сложение

Проверка дубликатов и их удаление

In [ ]:
df = pd.DataFrame({
    'A': ['1', '2', '4', '7', '10'],
    'B': ['ab', 'c', 'bc', 'ab', 'efd'],
    'C': [4, 4, 3.5, 15, 5]})

df
Out[ ]:
A B C
0 1 ab 4.0
1 2 c 4.0
2 4 bc 3.5
3 7 ab 15.0
4 10 efd 5.0
In [ ]:
df.drop_duplicates()
Out[ ]:
A B C
0 1 ab 4.0
1 2 c 4.0
2 4 bc 3.5
3 7 ab 15.0
4 10 efd 5.0

Если нужно удалить дубликаты по заданному набору полей, то есть параметр subset, в котором указывается по каким полям удалять дубликаты.

In [ ]:
df.drop_duplicates(subset=['B'])
Out[ ]:
A B C
0 1 ab 4.0
1 2 c 4.0
2 4 bc 3.5
4 10 efd 5.0

Удаление столбцов и строк. Отсутствующие значения.

In [ ]:
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, np.nan]})
df
Out[ ]:
A B C
0 1 4 7.0
1 2 5 8.0
2 3 6 NaN

Проверка на NaN-ы:

In [ ]:
df.isna()
Out[ ]:
A B C
0 False False False
1 False False False
2 False False True
In [ ]:
df.isna().sum()
Out[ ]:
A    0
B    0
C    1
dtype: int64

Удалять строки и столбцы с пустыми значениями можно с помощью функции dropna. Обратите внимание, что применение функции без присваивания создает новый объект, а не меняет df.

In [ ]:
df.dropna()
Out[ ]:
A B C
0 1 4 7.0
1 2 5 8.0

Как и у многих других функций библиотек numpy и pandas есть аргумент axis, который отвечает за выбор: просмотр строк или просмотр столбцов:

In [ ]:
df
Out[ ]:
A B C
0 1 4 7.0
1 2 5 8.0
2 3 6 NaN
In [ ]:
df.dropna(axis = 0)
Out[ ]:
A B C
0 1 4 7.0
1 2 5 8.0
In [ ]:
df.dropna(axis = 1)
Out[ ]:
A B
0 1 4
1 2 5
2 3 6

Пропущенные значения можно не только удалить, но и заполнить:

In [ ]:
df = pd.DataFrame([[np.nan, 2, np.nan, 0],
                   [3, 4, np.nan, 1],
                   [np.nan, np.nan, np.nan, np.nan],
                   [np.nan, 3, np.nan, 4]],
                columns=list("ABCD"))
df
Out[ ]:
A B C D
0 NaN 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 NaN NaN NaN NaN
3 NaN 3.0 NaN 4.0

Заполнить можно значением:

In [ ]:
df.fillna(value=0)
Out[ ]:
A B C D
0 0.0 2.0 0.0 0.0
1 3.0 4.0 0.0 1.0
2 0.0 0.0 0.0 0.0
3 0.0 3.0 0.0 4.0

Словарем значений:

In [ ]:
values = {"A": 0, "B": 1, "C": 2, "D": 3}
df.fillna(value=values)
Out[ ]:
A B C D
0 0.0 2.0 2.0 0.0
1 3.0 4.0 2.0 1.0
2 0.0 1.0 2.0 3.0
3 0.0 3.0 2.0 4.0

Методом заполнения вперед:

In [ ]:
df.fillna(method="ffill")
Out[ ]:
A B C D
0 NaN 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 3.0 4.0 NaN 1.0
3 3.0 3.0 NaN 4.0

Методом заполенения назад:

In [ ]:
df.fillna(method="bfill")
Out[ ]:
A B C D
0 3.0 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 NaN 3.0 NaN 4.0
3 NaN 3.0 NaN 4.0

И, конечно, нужно уметь удалять ненужные столбцы. Для этого есть функция drop. Здесь мы уже не обращаем внимание на наличие или отсутствие пустых значений. Параметрами подаются список названий колонок для удаления, и часто указывается axis=1, т.к. по умолчанию считается axis=0, в этом случае поиск будет по индексам строк.

In [ ]:
df.drop(["C"], axis = 1)
Out[ ]:
A B D
0 NaN 2.0 0.0
1 3.0 4.0 1.0
2 NaN NaN NaN
3 NaN 3.0 4.0
In [ ]:
df.fillna(method="bfill").drop(["A", "C"], axis = 1)
Out[ ]:
B D
0 2.0 0.0
1 4.0 1.0
2 3.0 4.0
3 3.0 4.0

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

In [ ]:
df = df.fillna(method="bfill").drop(["A", "C"], axis = 1)
In [ ]:
df
Out[ ]:
B D
0 2.0 0.0
1 4.0 1.0
2 3.0 4.0
3 3.0 4.0

Еще пара способов:

In [ ]:
df = pd.DataFrame([[np.nan, 2, np.nan, 0],
                   [3, 4, np.nan, 1],
                   [np.nan, np.nan, np.nan, np.nan],
                   [np.nan, 3, np.nan, 4]],
                columns=list("ABCD"))
df
Out[ ]:
A B C D
0 NaN 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 NaN NaN NaN NaN
3 NaN 3.0 NaN 4.0
In [ ]:
df.mean()
Out[ ]:
A    3.000000
B    3.000000
C         NaN
D    1.666667
dtype: float64
In [ ]:
df.fillna(df.mean())
Out[ ]:
A B C D
0 3.0 2.0 NaN 0.000000
1 3.0 4.0 NaN 1.000000
2 3.0 3.0 NaN 1.666667
3 3.0 3.0 NaN 4.000000
In [ ]:
df.fillna(df.min())
Out[ ]:
A B C D
0 3.0 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 3.0 2.0 NaN 0.0
3 3.0 3.0 NaN 4.0
In [ ]:
df.fillna(df.min()).fillna(df.max().min())
Out[ ]:
A B C D
0 3.0 2.0 3.0 0.0
1 3.0 4.0 3.0 1.0
2 3.0 2.0 3.0 0.0
3 3.0 3.0 3.0 4.0

Упражнение 1. Объясните, как работает ячейка выше.

In [ ]:
 

Упражнение 2. Дан датафрейм в ячейке ниже, состоящий из 4 единиц на диагонали и nan-ов. Заполнить его так, чтобы в нем было 8 единиц и 8 двоек. Использовать только fillna.

In [ ]:
df = pd.DataFrame([[1, np.nan, np.nan, np.nan],
                   [np.nan, 1, np.nan, np.nan],
                   [np.nan, np.nan, 1, np.nan],
                   [np.nan, np.nan, np.nan, 1]],
                columns=list("ABCD"))
df
Out[ ]:
A B C D
0 1.0 NaN NaN NaN
1 NaN 1.0 NaN NaN
2 NaN NaN 1.0 NaN
3 NaN NaN NaN 1.0
In [ ]:
df[1:2] = df[1:2].fillna(1)
df
Out[ ]:
A B C D
0 1.0 NaN NaN NaN
1 1.0 1.0 1.0 1.0
2 NaN NaN 1.0 NaN
3 NaN NaN NaN 1.0

Упражнение 3. Из полученного датафрейма удалить столбец (или столбцы) с минимальной суммой значений.

In [ ]:
 

Еще работа с данными. Пассажиры Титаника.

In [ ]:
df = pd.read_csv(r'train.csv') #поменять путь на актуальный для вас
In [ ]:
df.head()
Out[ ]:
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
In [ ]:
df.columns
Out[ ]:
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')
In [ ]:
df.shape
Out[ ]:
(891, 12)

Объединение датафреймов

В pandas для объединения датафреймов есть три метода pd.concat(), merge() и join(). Подробнее о них можно посмотреть: https://newtechaudit.ru/pandas-merge-join-concatenate/

Упражнение 4. Найдите средний возраст пассажиров

In [ ]:
 

Упражнение 5. Выведите имя самого молодого пассажира.

In [ ]:
 

Упражнение 6. Посчитайте доли пассажиров по классам обслуживания (Pclass)

In [ ]:
 

Упражнение 7. Найдите средние возраста пассажиров по классам обслуживания.

In [ ]:
 

Упражнение 8. Удалите столбец с наибольшим числом пропусков.

In [ ]:
 

Упражнение 9. Удалите столбцы с наибольшим числом уникальных значений.

In [ ]:
 

Упражнение 10. Найдите доли выживших среди мужчин, среди женщин и среди всех пассажиров.

In [ ]:
 

Упражнение 11. Найдите доли выживших по классам обслуживания.

In [ ]:
 

Упражнение 12. Найдите доли выживших среди возрастных категорий 18-, 18-60, 60+.

In [ ]:
 

Упражнение 13. Любым из рассмотренных методов реализуйте left join, right join, inner join, outer join датафреймов df1 и df2 (объединение по полю A).

In [ ]:
df1 = pd.DataFrame({
    'A': ['1', '2', '4', '7', '10'],
    'B': ['ab', 'c', 'bc', 'ab', 'efd'],
    'C': [4, 4, 3.5, 15, 5]})

df2 = pd.DataFrame({
    'A': ['1', '2', '4', '7', '10'],
    'F': ['n22', 'c1', 'b8', 'a589', 'b95'],
    'D': [100, 400, 30, 150, 50]})
In [ ]: