Решение задач анализа данных средствами 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()

Это особенно полезно, когда файл размером в несколько гигабайт.

Задачи с библиотекой Pandas - comments

En
Pandas python задачи (python)