Загрузка данных
Ниже приведено **пошаговое выполнение всех заданий** лабораторной работы №2 с использованием библиотек Pandas и NumPy. Код готов для копирования в Jupyter Notebook или Google Colab.
```python
# ========== Задание 1. Импорт библиотек и создание исходного DataFrame ==========
import numpy as np
import pandas as pd
data = {
'Name': ['Иван Петров', 'Мария Соколова', 'Петр Сидоров', 'Анна Козлова', 'Олег Смирнов'],
'Department': ['IT', 'HR', 'IT', 'Finance', 'HR'],
'Salary': [75000, 65000, 82000, 71000, 69000],
'Experience': [3, 5, 7, 2, 4]
}
df = pd.DataFrame(data)
print("Исходный DataFrame:")
print(df)
# ========== Задание 2. Переименование столбцов ==========
# Способ 1: через rename() с созданием копии
df_renamed = df.rename(columns={'Name': 'name', 'Department': 'dept', 'Salary': 'salary', 'Experience': 'exp'})
print("\nDataFrame после rename() с созданием копии:")
print(df_renamed)
# Способ 2: изменение на месте (inplace)
df.rename(columns={'Name': 'name', 'Department': 'dept', 'Salary': 'salary', 'Experience': 'exp'}, inplace=True)
print("\nDataFrame после rename() с inplace=True:")
print(df)
# Способ 3: прямое присваивание новых имён
df.columns = ['name', 'dept', 'salary', 'exp']
print("\nDataFrame после прямого присваивания:")
print(df)
# Ответ на вопрос:
# 1. rename(copy) – безопасно, не меняет исходный DataFrame.
# 2. rename(inplace) – меняет исходный, но менее предсказуем.
# 3. присваивание columns – быстро, но требует точного порядка и количества столбцов.
# Самый безопасный – rename с созданием копии.
# ========== Задание 3. Добавление новых столбцов ==========
# 3.1. Бонус (10% от зарплаты)
df['bonus'] = df['salary'] * 0.1
print("\nDataFrame с добавленным столбцом 'bonus':")
print(df)
# 3.2. Город через []
df['city'] = ['Москва', 'Санкт-Петербург', 'Москва', 'Казань', 'Новосибирск']
print("\nDataFrame с добавленным столбцом 'city':")
print(df)
# 3.3. Вставка gender на позицию 2
df.insert(2, 'gender', ['M', 'F', 'M', 'F', 'M'])
print("\nDataFrame после вставки столбца 'gender' на позицию 2:")
print(df)
# 3.4. Добавление нескольких столбцов через concat()
new_columns = pd.DataFrame({
'birth_year': [1990, 1988, 1985, 1992, 1989],
'phone': ['+7-901-123-45-67', '+7-902-234-56-78', '+7-903-345-67-89', '+7-904-456-78-90', '+7-905-567-89-01']
})
df = pd.concat([df, new_columns], axis=1)
print("\nDataFrame после добавления двух столбцов через concat():")
print(df)
# ========== Задание 4. Удаление столбцов ==========
# 4.1. Удаление одного столбца
df.drop('phone', axis=1, inplace=True)
print("\nDataFrame после удаления столбца 'phone':")
print(df)
# 4.2. Удаление нескольких столбцов
df.drop(['bonus', 'birth_year'], axis=1, inplace=True)
print("\nDataFrame после удаления столбцов 'bonus' и 'birth_year':")
print(df)
# 4.3. Альтернативный способ удаления (без inplace)
df = df.drop(['city'], axis=1)
print("\nDataFrame после удаления столбца 'city':")
print(df)
# ========== Задание 5. Добавление новых строк ==========
# 5.1. Добавление одной строки через loc[]
new_row_data = ['Елена Новикова', 'IT', 'F', 95000, 6]
df.loc[len(df)] = new_row_data
print("\nDataFrame после добавления одной строки через loc[]:")
print(df)
# 5.2. Добавление нескольких строк через concat()
new_rows = pd.DataFrame({
'name': ['Дмитрий Волков', 'Татьяна Морозова'],
'dept': ['Finance', 'HR'],
'gender': ['M', 'F'],
'salary': [88000, 72000],
'exp': [8, 3]
})
df = pd.concat([df, new_rows], ignore_index=True)
print("\nDataFrame после добавления двух строк через concat():")
print(df)
# ========== Задание 6. Конкатенация строк в столбце ==========
# 6.1. Простая конкатенация
df['full_info'] = df['name'] + ' (' + df['dept'] + ') - стаж: ' + df['exp'].astype(str) + ' лет'
print("\nDataFrame с новым столбцом 'full_info':")
print(df)
# 6.2. Использование str.cat()
df['name_dept'] = df['name'].str.cat(df['dept'], sep=' | ')
print("\nDataFrame с новым столбцом 'name_dept':")
print(df)
# 6.3. Удаление вспомогательного столбца
df.drop('full_info', axis=1, inplace=True)
print("\nDataFrame после удаления столбца 'full_info':")
print(df)
# ========== Задание 7. Замена содержимого и условная модификация ==========
# 7.1. Увеличение стажа на 1
df['exp'] = df['exp'] + 1
print("\nDataFrame после увеличения стажа на 1:")
print(df)
# 7.2. Повышение зарплаты IT на 10%
df.loc[df['dept'] == 'IT', 'salary'] = df.loc[df['dept'] == 'IT', 'salary'] * 1.1
print("\nDataFrame после повышения зарплаты сотрудникам IT:")
print(df)
# 7.3. Сложное условие: зарплата < 80000 и стаж > 4 → +5000
condition = (df['salary'] < 80000) & (df['exp'] > 4)
df.loc[condition, 'salary'] = df.loc[condition, 'salary'] + 5000
print("\nDataFrame после добавления бонуса 5000:")
print(df)
# 7.4. np.where()
df['bonus_flag'] = np.where(df['exp'] > 5, 'Senior', 'Junior')
print("\nDataFrame с новым столбцом 'bonus_flag':")
print(df)
# ========== Задание 8. Удаление строк ==========
# 8.1. Удаление строки с индексом 0
df.drop(0, axis=0, inplace=True)
print("\nDataFrame после удаления строки с индексом 0:")
print(df)
# 8.2. Удаление сотрудников с зарплатой < 80000
df = df[df['salary'] >= 80000].copy()
print("\nDataFrame после удаления сотрудников с зарплатой < 80000:")
print(df)
# 8.3. Удаление строк с индексами 2 и 4 (если существуют)
indices_to_drop = [2, 4]
existing_indices = [i for i in indices_to_drop if i in df.index]
df.drop(existing_indices, axis=0, inplace=True)
print("\nDataFrame после удаления строк с индексами 2 и 4:")
print(df)
# ========== Задание 9. Сброс индекса ==========
df.reset_index(drop=True, inplace=True)
print("\nDataFrame после сброса индекса:")
print(df)
# ========== Задание 10. Логический отбор и создание срезов ==========
# 10.1. Сотрудники HR
selected = df.loc[df['dept'] == 'HR', ['name', 'salary', 'exp']]
print("\nСотрудники HR (имя, зарплата, стаж):")
print(selected)
# 10.2. Первые 3 строки, столбцы 0,1,3
first_three = df.iloc[:3, [0, 1, 3]]
print("\nПервые три строки (выборочные столбцы):")
print(first_three)
# 10.3. Зарплата выше среднего
avg_salary = df['salary'].mean()
high_earners = df.loc[df['salary'] > avg_salary, ['name', 'dept', 'salary']]
print("\nСотрудники с зарплатой выше среднего:")
print(high_earners)
# ========== Задание 11. Сохранение и загрузка ==========
df.to_csv('employees_modified.csv', index=False, encoding='utf-8')
print("\nDataFrame сохранён в 'employees_modified.csv'")
df_loaded = pd.read_csv('employees_modified.csv')
print("\nЗагруженный DataFrame:")
print(df_loaded)
print("\nСовпадение данных:", df.equals(df_loaded))
# ========== Дополнительное задание (группировка) ==========
dept_stats = df.groupby('dept').agg({
'salary': ['mean', 'min', 'max'],
'exp': 'mean'
}).round(0)
print("\nСтатистика по отделам:")
print(dept_stats)
dept_stats.to_csv('department_stats.csv')
print("\nСтатистика сохранена в 'department_stats.csv'")
# ========== Задания для самостоятельной работы ==========
# 1. Создание DataFrame о продажах
np.random.seed(42)
sales_data = {
'date': pd.date_range('2025-01-01', periods=10, freq='D'),
'product': ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A'],
'category': ['Electronics', 'Clothing', 'Electronics', 'Electronics', 'Clothing', 'Electronics', 'Electronics', 'Clothing', 'Electronics', 'Electronics'],
'price': np.random.randint(100, 1000, 10),
'quantity': np.random.randint(1, 10, 10)
}
df_sales = pd.DataFrame(sales_data)
df_sales['revenue'] = df_sales['price'] * df_sales['quantity']
print("\nDataFrame продаж:")
print(df_sales)
# 2. Топ-3 товара по выручке
top_products = df_sales.groupby('product')['revenue'].sum().sort_values(ascending=False).head(3)
print("\nТоп-3 товара по выручке:")
print(top_products)
# 3. Категория цены
df_sales['price_category'] = pd.cut(df_sales['price'], bins=[0, 300, 700, 1000], labels=['Low', 'Medium', 'High'])
print("\nDataFrame с ценовой категорией:")
print(df_sales)
# 4. Удалить строки, где quantity < 2
df_sales = df_sales[df_sales['quantity'] >= 2].copy()
print("\nDataFrame после удаления quantity < 2:")
print(df_sales)
# 5. Группировка по категориям и общая выручка
category_revenue = df_sales.groupby('category')['revenue'].sum()
print("\nОбщая выручка по категориям:")
print(category_revenue)
```
## Ответы на контрольные вопросы (кратко):
1. **Способы переименования**: `rename()` (с копией или inplace), прямое присваивание `df.columns`. Плюсы: безопасность vs скорость.
2. **Вставка столбца в позицию**: `df.insert(позиция, 'имя', данные)`.
3. **drop() vs del**: `drop()` может удалять несколько столбцов/строк и работать с копией, `del` — только один столбец, на месте.
4. **Сброс индекса** нужен, чтобы избежать пропусков и ошибок при отборе.
5. **`pd.concat([df, new_rows], ignore_index=True)`** — объединяет и переиндексирует.
6. **`.loc[]`** — по меткам (включая условия), **`.iloc[]`** — по целочисленным позициям.
7. **`df.loc[условие, 'столбец'] = новое_значение`**.
8. **`str.cat()`** — объединяет строки с разделителем, например `df['a'].str.cat(df['b'], sep='-')`.
9. **`to_csv(index=False)`** — чтобы избежать лишнего столбца с индексами при загрузке.
10. При удалении несуществующего столбца/строки будет **ошибка KeyError**.
Весь код готов к запуску. Если нужен файл `.ipynb` — скачайте его или скопируйте в Google Colab.