Решение задач анализа данных средствами Pandas
Pandas
- это библиотека Python для анализа данных, предоставляющая высокоуровневые структуры DataFrame и Series. В задачах научных вычислений часто требуются операции загрузки, очистки, трансформации и агрегации данных. Ниже рассмотрены типовые ситуации с примерами кода.Загрузка данных из CSV и Excel
Наиболее распространённый способ чтения табличных данных - функция pd.read_csv(). Для файлов Excel используется pd.read_excel(). Параметр sep задаёт разделитель, header - строку с заголовками.
# Чтение CSV с разделителем-запятой
import pandas as pd
df = pd.read_csv('data.csv', sep=',')
Python для инженерных задач (python для инженерных задач)
# Чтение Excel, первый лист
xls = pd.ExcelFile('file.xlsx')
df = pd.read_excel(xls, sheet_name=0)
задачи для анализа данных python (задачи анализа данных на python)
Если файл содержит строки с ошибками кодировки, укажите encoding='utf-8' или encoding='cp1251'.
Как загрузить только часть столбцов?
Используйте параметр usecols:
df = pd.read_csv('data.csv', usecols=['name', 'age'])
задачи линейного программирования python (задачи линейного программирования на python)
Типичная ошибка:
При чтении Excel с несколькими листами без указания sheet_name загружается только первый лист. Решение - передать список имён или индекс листа.
df_dict = pd.read_excel('file.xlsx', sheet_name=['Sheet1', 'Sheet2'])
Pandas python задачи (задачи с библиотекой pandas)
Первичный осмотр данных
Методы df.head(), df.info(), df.describe() дают быстрое представление о структуре.
# Первые 5 строк
df.head()
# Статистика числовых столбцов
df.describe()
# Общая информация о типах и пропусках
print(df.info())
ии для решения задач на python (использование ии для решения задач на python)
Как посмотреть количество уникальных значений в столбце?
Метод value_counts() возвращает частоты.
df['city'].value_counts()
Если данные большие, вызов df.head() без аргумента может показать только первые 5 строк, что не всегда информативно. Используйте df.sample(10) для случайных строк.
Выборка и фильтрация строк
Булева индексация - основа фильтрации. Например, выбрать строки с возрастом больше 30:
filtered = df[df['age'] > 30]
Метод loc позволяет выбирать по меткам или условиям сразу.
# Строки 10:20 и столбцы 'name','salary'
df.loc[10:20, ['name','salary']]
Как выполнить фильтрацию по нескольким условиям?
Используйте логические операторы & (и), | (или), обязательно оборачивая условия в скобки.
df[(df['age'] > 25) & (df['city'] == 'Moscow')]
Распространённая ошибка:
Забывают скобки вокруг условий, что приводит к ошибке или неверному результату из-за приоритета операторов.
Обработка пропущенных значений
Удаление строк с NaN:
df_clean = df.dropna()
Замена пропусков средним по столбцу:
df['salary'].fillna(df['salary'].mean(), inplace=True)
Как заполнить пропуски разными значениями для разных столбцов?
Передайте словарь в fillna.
values = {'age': 0, 'salary': 1000}
df = df.fillna(value=values)
Заполнение средним может исказить распределение. Для категориальных данных лучше использовать моду или константу 'Unknown'. Выбор зависит от задачи.
Удаление дубликатов
Метод drop_duplicates() удаляет повторяющиеся строки. Параметр keep определяет, какую из дублей оставить.
df_unique = df.drop_duplicates(subset=['user_id'], keep='first')
Как найти дубликаты, не удаляя их?
Используйте df.duplicated(), возвращающий булев массив.
df[df.duplicated()]
Перед удалением проверьте, не являются ли дубликаты допустимыми повторными измерениями. Удаление без анализа может потерять данные.
Группировка и агрегация
Классический пример - средняя зарплата по городам:
grouped = df.groupby('city')['salary'].mean()
Как применить несколько агрегаций одновременно?
Метод agg принимает список или словарь.
df.groupby('city')['salary'].agg(['mean', 'std', 'count'])
После группировки получается объект GroupBy. Если пытаться применить метод head() к нему напрямую, будет ошибка. Используйте df.groupby(...).head().
Создание новых столбцов
Добавление вычисленного поля:
df['full_name'] = df['first_name'] + ' ' + df['last_name']
Как применить функцию к каждому элементу столбца?
Метод apply принимает пользовательскую функцию.
def categorize(age):
return 'young' if age < 30 else 'adult'
df['category'] = df['age'].apply(categorize)
apply работает медленно на больших данных. Лучше использовать векторизованные операции (например, numpy.where).
Работа с датами
Преобразование строки в datetime и извлечение года:
df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
Как сгруппировать по месяцам?
Используйте resample после установки индекса-даты.
df.set_index('date', inplace=True)
df_monthly = df.resample('M').sum()
Если даты записаны в нестандартном формате, укажите format в to_datetime. Иначе могут возникнуть ошибки времени выполнения или некорректные значения.
pd.to_datetime(df['date'], format='%d/%m/%Y')
Слияние таблиц
Соединение по ключу через merge:
df = pd.merge(df_left, df_right, on='user_id', how='left')
Как объединить несколько таблиц последовательно?
concat склеивает по строкам или столбцам.
df_all = pd.concat([df1, df2, df3], axis=0, ignore_index=True)
При merge по умолчанию how='inner', что может исключить строки без совпадений. Если нужно сохранить все строки левой таблицы, используйте how='left'.
Перестройка таблиц (pivot)
Сводная таблица (pivot):
pivot = df.pivot_table(index='city', columns='year', values='sales', aggfunc='sum')
Как превратить сводную таблицу обратно в плоский формат?
Метод melt (melt).
df_melted = pd.melt(pivot.reset_index(), id_vars=['city'], var_name='year', value_name='sales')
Если в исходной таблице несколько значений для одной комбинации индекс-столбец, нужна агрегация (aggfunc), иначе возникнет ошибка.
Расширенные примеры задач с Pandas
1. Загрузка данных с пропусками и неправильными типами
Файл CSV может содержать столбцы с смешанными типами. При чтении указание dtype ускоряет загрузку и предотвращает ошибки.
# Принудительно задать тип int для столбца 'id'
df = pd.read_csv('sales.csv', dtype={'id': int, 'amount': float})
# Вывод info (пример) <class 'pandas.core.frame.DataFrame'> RangeIndex: 1000 entries, 0 to 999 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 1000 non-null int64 1 product 950 non-null object 2 amount 980 non-null float64 3 date 1000 non-null object 4 region 800 non-null object
Пропуски в столбце 'product' можно заполнить строкой 'unknown' с помощью fillna.
df['product'] = df['product'].fillna('unknown')
2. Комбинированная фильтрация по нескольким условиям
Выбрать заказы из Москвы с суммой больше 1000, кроме тех, что были сделаны в выходные (считаем, что дата хранится в datetime).
# Создаём булевы маски
mask_city = df['city'] == 'Moscow'
mask_amount = df['amount'] > 1000
mask_weekend = df['date'].dt.dayofweek.isin([5,6]) # суббота, воскресенье
filtered = df[mask_city & mask_amount & ~mask_weekend]
# Результат (первые строки)
id city amount date
2 102 Moscow 1500.5 2023-10-12
5 105 Moscow 2200.0 2023-10-15
...
3. Группировка с применением пользовательской функции
Есть данные о продажах. Нужно для каждой категории товара найти разницу между максимальной и минимальной ценой.
def price_range(group):
return group['price'].max() - group['price'].min()
result = df.groupby('category').apply(price_range)
# Результат (серия) category Electronics 3400 Food 250 Clothing 800
4. Слияние трёх таблиц с разными ключами
Есть таблица пользователей (id, name), таблица заказов (user_id, order_id, amount) и таблица оплат (order_id, payment_date). Требуется получить полный датасет.
users = pd.DataFrame({'id': [1,2,3], 'name': ['Alex','Bob','Cara']})
orders = pd.DataFrame({'user_id': [1,1,2], 'order_id': [101,102,103], 'amount': [100,200,150]})
payments = pd.DataFrame({'order_id': [101,102,103], 'payment_date': ['2023-01-01','2023-01-02','2023-01-03']})
# Цепочка merge
df_merged = users.merge(orders, left_on='id', right_on='user_id', how='left') \
.merge(payments, on='order_id', how='left')
id name user_id order_id amount payment_date 0 1 Alex 1 101 100 2023-01-01 1 1 Alex 1 102 200 2023-01-02 2 2 Bob 2 103 150 2023-01-03 3 3 Cara NaN NaN NaN NaN
5. Работа с временными рядами: агрегация по неделям и заполнение пропусков
Дневные данные, есть пропуски. Сгруппировать по неделям (начиная с понедельника), заполнить пропуски средним за предыдущие 3 дня.
# Допустим, индекс - дата
df.index = pd.to_datetime(df.index)
df_weekly = df.resample('W-MON').sum()
# Заменим NaN на среднее за окно 3 строк (недели)
df_weekly_filled = df_weekly.fillna(df_weekly.rolling(3, min_periods=1).mean())
# Пример фрагмента
sales
date
2023-01-02 450.0
2023-01-09 510.0
2023-01-16 490.0
2023-01-23 NaN
2023-01-30 520.0
# После заполнения
2023-01-23 490.0 (среднее за 09-16-23? фактически 500)
6. Применение pipe для создания цепочек трансформаций
Объединение нескольких операций (фильтрация, добавление столбца, группировка) в читаемый поток.
def filter_high(df, threshold=1000):
return df[df['amount'] > threshold]
def add_tax(df, tax_rate=0.2):
df['tax'] = df['amount'] * tax_rate
return df
def group_city(df):
return df.groupby('city')['tax'].sum()
result = (df
.pipe(filter_high, threshold=500)
.pipe(add_tax, tax_rate=0.1)
.pipe(group_city)
)
city Moscow 1200 London 800 ...
7. Использование query для фильтрации с переменными
Метод query делает код компактнее, особенно при множестве условий.
city_filter = 'London'
min_salary = 50000
df_filtered = df.query('city == @city_filter and salary >= @min_salary')
# Результат: только строки по Лондону с зарплатой >= 50000
8. Параллельное применение функций с swifter (для больших данных)
Если обычный apply медленный, используйте библиотеку swifter для параллельного выполнения.
import swifter
df['result'] = df['some_column'].swifter.apply(complex_function)
Установка: pip install swifter. Swifter автоматически выбирает число потоков и ускоряет работу в несколько раз.
9. Обработка вложенных JSON в столбцах
Если в DataFrame есть столбец со словарями или списками, его можно 'распаковать' с помощью json_normalize.
import json
from pandas import json_normalize
df = pd.DataFrame({'id': [1,2], 'details': ['{"name":"A","score":10}', '{"name":"B","score":20}']})
df['details_parsed'] = df['details'].apply(json.loads)
df_details = json_normalize(df['details_parsed'])
df = pd.concat([df[['id']], df_details], axis=1)
id name score 0 1 A 10 1 2 B 20
10. Оптимизация памяти при чтении больших файлов
Параметр chunksize позволяет обрабатывать данные частями, не загружая весь файл в память.
chunks = pd.read_csv('bigdata.csv', chunksize=10000)
result = []
for chunk in chunks:
chunk_filtered = chunk[chunk['year'] == 2023]
result.append(chunk_filtered.groupby('region')['sales'].sum())
final = pd.concat(result).groupby(level=0).sum()
Это особенно полезно, когда файл размером в несколько гигабайт.