|
Объединение, слияние и работа с пропусками в Pandas
ОП.09 Обработка и анализ данных
Практическая работа №4
Тема: Объединение, слияние и работа с пропусками в Pandas
Цель работы: Научиться объединять несколько датафреймов, выполнять слияние по ключевым полям, обрабатывать пропущенные значения различными методами.
Время выполнения: 2 академических часа
Инструменты: Python + Jupyter Notebook, библиотеки pandas, numpy
ЗАДАНИЕ ДЛЯ СТУДЕНТА
Этап 1. Создание нескольких датафреймов (10 минут)
Создадим три датафрейма для демонстрации объединения:
import pandas as pd
import numpy as np
# Датафрейм 1: студенты и их группы
students = pd.DataFrame({
'student_id': [1, 2, 3, 4, 5],
'name': ['Анна', 'Борис', 'Виктор', 'Галина', 'Дмитрий'],
'group': ['ИС-21', 'ИС-21', 'ИС-22', 'ИС-22', 'ИС-23']
})
print("Студенты:")
print(students)
# Датафрейм 2: оценки по предметам
grades = pd.DataFrame({
'student_id': [1, 2, 3, 4, 5, 1, 2, 3],
'subject': ['Математика', 'Математика', 'Математика', 'Математика', 'Математика',
'Физика', 'Физика', 'Физика'],
'score': [5, 4, 3, 5, 4, 4, 3, 4]
})
print("Оценки:")
print(grades)
# Датафрейм 3: дополнительная информация
extra = pd.DataFrame({
'student_id': [1, 2, 6, 7],
'email': ['anna@edu.ru', 'boris@edu.ru', 'ivan@edu.ru', 'olga@edu.ru']
})
print("Доп. информация:")
print(extra)
Этап 2. Объединение строк (concat) (10 минут)
Используйте concat для вертикального и горизонтального объединения:
# Вертикальное объединение (добавляем строки)
students2 = pd.DataFrame({
'student_id': [6, 7],
'name': ['Елена', 'Жанна'],
'group': ['ИС-23', 'ИС-24']
})
all_students = pd.concat([students, students2])
print("Все студенты (вертикальное объединение):")
print(all_students)
# Горизонтальное объединение (добавляем столбцы)
more_info = pd.DataFrame({
'city': ['Москва', 'СПб', 'Казань', 'НН', 'Екб'],
'age': [19, 20, 21, 20, 19]
})
students_with_city = pd.concat([students, more_info], axis=1)
print("Студенты с городом (горизонтальное объединение):")
print(students_with_city)
Вопрос: Что произойдёт, если при горизонтальном объединении количество строк разное?
Этап 3. Слияние таблиц (merge) (15 минут)
Выполните различные типы слияний:
# Inner join (только те, у кого есть оценки)
inner_merge = pd.merge(students, grades, on='student_id', how='inner')
print("Inner join (только студенты с оценками):")
print(inner_merge)
# Left join (все студенты)
left_merge = pd.merge(students, grades, on='student_id', how='left')
print("Left join (все студенты, оценки где есть):")
print(left_merge)
# Right join (все оценки)
right_merge = pd.merge(students, grades, on='student_id', how='right')
print("Right join (все оценки):")
print(right_merge)
# Outer join (все данные из обеих таблиц)
outer_merge = pd.merge(students, extra, on='student_id', how='outer')
print("Outer join (все студенты + доп. контакты):")
print(outer_merge)
Вопросы:
• Какой тип слияния сохраняет всех студентов, даже если у них нет оценок?
• Что появится в ячейках при отсутствии данных в left/right merge?
Этап 4. Работа с пропусками (NaN) (20 минут)
Создадим датафрейм с пропусками и научимся их обрабатывать:
# Создаём данные с пропусками
df_with_nan = pd.DataFrame({
'name': ['Анна', 'Борис', 'Виктор', 'Галина', 'Дмитрий'],
'math': [5, 4, np.nan, 5, 4],
'physics': [4, np.nan, 3, 5, np.nan],
'informatics': [5, 5, 4, np.nan, 4]
})
print("Исходные данные с пропусками:")
print(df_with_nan)
# 1. Проверка на пропуски
print("Сколько пропусков в каждом столбце:")
print(df_with_nan.isnull().sum())
# 2. Удаление строк с пропусками
dropped_rows = df_with_nan.dropna()
print("После удаления всех строк с пропусками:")
print(dropped_rows)
# 3. Заполнение пропусков средним значением
df_filled_mean = df_with_nan.copy()
df_filled_mean['math'] = df_filled_mean['math'].fillna(df_filled_mean['math'].mean())
df_filled_mean['physics'] = df_filled_mean['physics'].fillna(df_filled_mean['physics'].mean())
df_filled_mean['informatics'] = df_filled_mean['informatics'].fillna(df_filled_mean['informatics'].mean())
print("После заполнения средним значением:")
print(df_filled_mean)
# 4. Заполнение пропусков заданным значением
df_filled_value = df_with_nan.fillna(0)
print("После заполнения нулями:")
print(df_filled_value)
# 5. Заполнение пропусков предыдущим значением (ffill)
df_ffill = df_with_nan.fillna(method='ffill')
print("После заполнения предыдущим значением:")
print(df_ffill)
Вопросы:
• Какой метод заполнения лучше использовать для числовых данных?
• В каких случаях уместно удалять строки с пропусками?
Этап 5. Практическое задание: объединение данных о фильмах (20 минут)
Даны две таблицы с информацией о фильмах и рейтингах:
# Таблица фильмов
movies = pd.DataFrame({
'movie_id': [1, 2, 3, 4, 5],
'title': ['Побег из Шоушенка', 'Крёстный отец', 'Тёмный рыцарь', 'Криминальное чтиво', 'Властелин колец'],
'year': [1994, 1972, 2008, 1994, 2001]
})
print("Фильмы:")
print(movies)
# Таблица рейтингов (с пропусками)
ratings = pd.DataFrame({
'movie_id': [1, 2, 3, 4, 5, 1, 2, 3, 4],
'user_id': [101, 101, 101, 101, 101, 102, 102, 102, 102],
'rating': [9.5, 9.0, 9.0, 8.5, np.nan, 9.0, 8.5, 8.0, 9.0]
})
print("Рейтинги:")
print(ratings)
Выполните задания:
# 1. Объедините movies и ratings, чтобы получить полную информацию о каждом рейтинге
full_ratings = pd.merge(ratings, movies, on='movie_id', how='left')
print("Полная информация о рейтингах:")
print(full_ratings)
# 2. Рассчитайте средний рейтинг для каждого фильма (предварительно удалив пропуски)
clean_ratings = ratings.dropna()
avg_rating = clean_ratings.groupby('movie_id')['rating'].mean()
print("Средний рейтинг каждого фильма:")
print(avg_rating)
# 3. Добавьте средний рейтинг к таблице фильмов
movies_with_rating = pd.merge(movies, avg_rating.reset_index(), on='movie_id', how='left')
movies_with_rating.rename(columns={'rating': 'avg_rating'}, inplace=True)
print("Фильмы со средним рейтингом:")
print(movies_with_rating)
# 4. Заполните пропуски среднего рейтинга (если нет оценок) значением 0
movies_with_rating['avg_rating'] = movies_with_rating['avg_rating'].fillna(0)
print("После заполнения пропусков:")
print(movies_with_rating)
Вопрос: Почему при расчёте среднего рейтинга нужно удалять пропуски?
Этап 6. Работа с реальным датасетом (20 минут)
Вернёмся к датасету titanic.csv и выполним дополнительные операции:
# Загружаем датасет
df = pd.read_csv('titanic.csv')
# 1. Сколько пропусков в каждом столбце?
print("Пропуски в titanic.csv:")
print(df.isnull().sum())
# 2. Удалите столбцы с большим количеством пропусков (> 500)
# Cabin имеет 687 пропусков — удалим его
df_clean = df.drop('Cabin', axis=1)
# 3. Заполните пропуски в Age средним значением
df_clean['Age'] = df_clean['Age'].fillna(df_clean['Age'].mean())
# 4. Заполните пропуски в Embarked наиболее частым значением
most_common = df_clean['Embarked'].mode()[0]
df_clean['Embarked'] = df_clean['Embarked'].fillna(most_common)
# 5. Проверьте, остались ли пропуски
print("Пропуски после обработки:")
print(df_clean.isnull().sum())
Этап 7. Выводы (10 минут)
Напишите развёрнутый вывод по работе:
1. В чём разница между concat и merge?
2. Какие типы слияний (inner, left, right, outer) существуют и когда их применяют?
3. Какие методы обработки пропусков вы использовали? Какой метод подходит для разных ситуаций?
4. Почему важно правильно обрабатывать пропуски перед анализом данных?
КРИТЕРИИ ОЦЕНКИ
| Критерий | Макс. балл |
|---|
|
| Все этапы выполнены (1-6) | 3 | | Корректное использование concat и merge | 2 | | Правильная обработка пропусков (разными методами) | 2 | | Практическое задание выполнено верно | 1 | | Выводы осмысленные, примеры из работы | 2 | | Итого | 10 |
ОТВЕТ ДЛЯ ПРЕПОДАВАТЕЛЯ (эталонный результат)
Нажмите, чтобы увидеть ответы
Этап 2. concat:
• При горизонтальном объединении с разным количеством строк появится NaN.
Этап 3. merge:
• Left join сохраняет всех студентов, даже без оценок.
• При отсутствии данных появляется NaN.
Этап 4. Обработка пропусков:
• Для числовых данных лучше подходит заполнение средним/медианой.
• Удаление строк уместно, если пропусков мало (менее 5%) и данные не критичны.
Этап 5. Фильмы:
• Пропуски удаляют, потому что среднее от NaN даёт NaN.
Этап 6. Titanic:
• До обработки пропуски: Age (177), Cabin (687), Embarked (2).
• После обработки пропусков нет ни в одном столбце.
Этап 7. Выводы (пример):
1. Concat — простое склеивание строк/столбцов, merge — слияние по ключу.
2. Inner — пересечение, left/right — с приоритетом одной таблицы, outer — всё.
3. Использовали: dropna, fillna(mean), fillna(value), ffill.
4. Без обработки пропусков многие функции (mean, groupby) работают некорректно.
Автор: УМК СПО
Лицензия: Бесплатное использование с указанием источника
|
|
|