Создание и фильтрация датафреймов в pandas: руководство для новичков
Для кого эта статья:
- начинающие аналитики данных
- студенты и профессионалы, желающие улучшить навыки работы с pandas
специалисты, интересующиеся эффективными методами анализа данных в Python
Когда впервые сталкиваешься с анализом данных в Python, библиотека pandas кажется непреодолимой стеной сложных функций и методов. Я помню свой первый день с pandas: десятки ошибок в коде, непонятные названия методов и полное отчаяние. Но стоило освоить создание и фильтрацию датафреймов — и внезапно открылся целый мир возможностей для работы с данными. Эта статья — ваш ключ к освоению фундаментальных навыков pandas, которые превратят хаос чисел в управляемые, логичные структуры. 📊
Хотите изучить pandas глубоко и системно? Курс Профессия аналитик данных от Skypro погружает в мир обработки данных через практические задачи. Вы не просто изучите pandas — вы научитесь создавать, фильтровать и трансформировать датафреймы на реальных проектах под руководством опытных аналитиков. В отличие от фрагментарных туториалов, курс даёт последовательную систему знаний, которая превратит вас в настоящего повелителя данных.
Создание датафреймов в pandas: 5 основных способов
Датафрейм — это двумерная структура данных в pandas, похожая на таблицу в Excel или SQL. Это ключевой инструмент для любого аналитика данных. Рассмотрим 5 основных способов создания датафреймов, от простейших до продвинутых.
Прежде всего, импортируем необходимые библиотеки:
import pandas as pd
import numpy as np
Способ 1: Создание из словаря
Самый простой способ — создать датафрейм из словаря Python, где ключи станут именами столбцов:
data = {
'Имя': ['Анна', 'Иван', 'Мария', 'Алексей'],
'Возраст': [28, 32, 25, 41],
'Город': ['Москва', 'Санкт-Петербург', 'Казань', 'Новосибирск']
}
df = pd.DataFrame(data)
print(df)
Способ 2: Создание из списков
Можно создать датафрейм из списка списков, указав имена столбцов отдельно:
data = [
['Анна', 28, 'Москва'],
['Иван', 32, 'Санкт-Петербург'],
['Мария', 25, 'Казань'],
['Алексей', 41, 'Новосибирск']
]
df = pd.DataFrame(data, columns=['Имя', 'Возраст', 'Город'])
print(df)
Способ 3: Создание из массива NumPy
Если ваши данные уже хранятся в виде NumPy массива:
data = np.array([
['Анна', 28, 'Москва'],
['Иван', 32, 'Санкт-Петербург'],
['Мария', 25, 'Казань'],
['Алексей', 41, 'Новосибирск']
])
df = pd.DataFrame(data, columns=['Имя', 'Возраст', 'Город'])
print(df)
Способ 4: Создание с помощью Series
Series — это одномерный массив с метками, который можно использовать для создания столбцов датафрейма:
name = pd.Series(['Анна', 'Иван', 'Мария', 'Алексей'])
age = pd.Series([28, 32, 25, 41])
city = pd.Series(['Москва', 'Санкт-Петербург', 'Казань', 'Новосибирск'])
df = pd.DataFrame({
'Имя': name,
'Возраст': age,
'Город': city
})
print(df)
Способ 5: Пустой датафрейм с последующим заполнением
Иногда требуется создать пустой датафрейм и заполнить его позже:
df = pd.DataFrame(columns=['Имя', 'Возраст', 'Город'])
df.loc[0] = ['Анна', 28, 'Москва']
df.loc[1] = ['Иван', 32, 'Санкт-Петербург']
print(df)
| Способ | Преимущества | Недостатки | Лучше использовать, когда... |
|---|---|---|---|
| Словарь | Интуитивно понятно, чистый код | Ограничения при сложных структурах | Данные уже структурированы по столбцам |
| Списки | Гибкость в создании структур | Требует отдельного указания столбцов | Данные уже структурированы по строкам |
| NumPy массив | Высокая производительность | Ограничения по типам данных | Работаете с числовыми данными |
| Series | Точный контроль над метками индексов | Более многословный код | Нужны разные индексы для столбцов |
| Пустой датафрейм | Максимальная гибкость | Низкая производительность при больших объёмах | Данные поступают постепенно |
Михаил Соколов, старший аналитик данных
Когда я начинал работать с финансовой аналитикой в инвестиционном проекте, мне требовалось обрабатывать ежедневные транзакции из множества источников. Поначалу я создавал датафреймы вручную из словарей, и это занимало часы. Всё изменилось, когда я научился автоматизировать создание датафреймов из разных источников.
Я написал функцию, которая собирала данные из CSV-файлов, JSON-ответов API и SQL-запросов, формируя единый датафрейм. Благодаря pandas мне удалось сократить время формирования отчётов с 3-4 часов до 15 минут. Ключом к успеху стало понимание того, что для разных источников данных нужны разные подходы к созданию датафреймов, а также умение объединять их с помощью методов concat и merge.

Создание и настройка датафреймов из разных источников
Реальные проекты редко ограничиваются созданием датафреймов вручную. Чаще всего данные поступают из внешних источников — файлов, баз данных или API. Рассмотрим, как работать с такими источниками и правильно настраивать получаемые датафреймы. 🗂️
Чтение из CSV-файлов
CSV (Comma Separated Values) — один из самых распространенных форматов для хранения табличных данных:
# Базовое чтение CSV
df = pd.read_csv('data.csv')
# Чтение с дополнительными параметрами
df = pd.read_csv('data.csv',
sep=';', # разделитель
encoding='utf-8', # кодировка
index_col=0, # столбец для индекса
parse_dates=['date_column']) # парсинг дат
Чтение из Excel-файлов
Для работы с Excel требуется установить дополнительные библиотеки (openpyxl или xlrd):
# Чтение из Excel
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
# Чтение нескольких листов
sheets = pd.read_excel('data.xlsx', sheet_name=None) # словарь с датафреймами
Чтение из SQL-баз данных
Pandas может напрямую читать данные из баз данных:
from sqlalchemy import create_engine
# Создание подключения к базе данных
engine = create_engine('sqlite:///database.db')
# Чтение данных из SQL-запроса
df = pd.read_sql_query('SELECT * FROM table_name', engine)
# Чтение целой таблицы
df = pd.read_sql_table('table_name', engine)
Чтение JSON-данных
JSON часто используется в API и веб-сервисах:
# Из JSON-файла
df = pd.read_json('data.json')
# Из JSON-строки
import json
with open('data.json', 'r') as f:
data = json.load(f)
df = pd.DataFrame(data)
Настройка датафреймов после импорта
После импорта часто требуется дополнительная настройка датафрейма:
- Переименование столбцов:
df.rename(columns={'old_name': 'new_name'}, inplace=True) - Изменение типов данных:
df['column'] = df['column'].astype('int') - Обработка пропущенных значений:
df.fillna(0, inplace=True)илиdf.dropna(inplace=True) - Установка индекса:
df.set_index('id_column', inplace=True) - Сортировка данных:
df.sort_values('column', ascending=False, inplace=True)
Пример комплексной настройки датафрейма после импорта:
# Импорт данных
df = pd.read_csv('sales_data.csv')
# Комплексная настройка
df = (df
.rename(columns={'DATE': 'date', 'PROD_ID': 'product_id', 'QTY': 'quantity'})
.assign(date=lambda x: pd.to_datetime(x['date']))
.fillna({'quantity': 0, 'price': 0})
.assign(total=lambda x: x['quantity'] * x['price'])
.sort_values('date')
.reset_index(drop=True)
)
Базовые методы фильтрации датафреймов в pandas
Умение фильтровать данные — одно из ключевых навыков аналитика. Pandas предлагает несколько мощных методов для отбора нужных строк и столбцов из датафреймов. 🔍
Фильтрация с помощью булевых масок
Самый гибкий способ фильтрации — использование булевых масок:
# Создаём пример датафрейма
df = pd.DataFrame({
'имя': ['Анна', 'Иван', 'Мария', 'Алексей', 'Елена'],
'возраст': [28, 32, 25, 41, 38],
'город': ['Москва', 'Санкт-Петербург', 'Москва', 'Казань', 'Москва'],
'зарплата': [85000, 120000, 70000, 100000, 95000]
})
# Простая фильтрация по одному условию
москвичи = df[df['город'] == 'Москва']
# Фильтрация по нескольким условиям (AND)
молодые_москвичи = df[(df['город'] == 'Москва') & (df['возраст'] < 30)]
# Фильтрация по нескольким условиям (OR)
москвичи_или_богатые = df[(df['город'] == 'Москва') | (df['зарплата'] > 100000)]
Метод .loc для фильтрации по метке
Метод .loc используется для доступа к данным по метке (имени) строки или столбца:
# Выбор по индексу строки и имени столбца
df.loc[0, 'имя'] # Анна
# Выбор нескольких строк и столбцов
df.loc[0:2, ['имя', 'возраст']]
# Фильтрация строк с условиями
df.loc[df['город'] == 'Москва', ['имя', 'зарплата']]
Метод .iloc для фильтрации по позиции
Метод .iloc используется для доступа к данным по числовой позиции (как в обычном списке):
# Выбор по позиции строки и столбца
df.iloc[0, 0] # Анна (первая строка, первый столбец)
# Выбор нескольких строк и столбцов по позиции
df.iloc[0:2, 1:3] # Первые 2 строки, 2-й и 3-й столбцы
# Выбор отдельных строк и столбцов по позиции
df.iloc[[0, 2], [1, 3]] # 1-я и 3-я строки, 2-й и 4-й столбцы
Метод .query() для удобной фильтрации
Метод .query() позволяет писать условия фильтрации в виде строки, что иногда удобнее для сложных запросов:
# Фильтрация с помощью query
москвичи = df.query("город == 'Москва'")
# Сложные условия
москвичи_или_богатые = df.query("город == 'Москва' or зарплата > 100000")
# Использование переменных с @
порог_зарплаты = 90000
высокооплачиваемые = df.query("зарплата > @порог_зарплаты")
Фильтрация с помощью .isin()
Метод .isin() позволяет проверять вхождение в список значений:
# Фильтрация по списку значений
крупные_города = ['Москва', 'Санкт-Петербург']
жители_крупных_городов = df[df['город'].isin(крупные_города)]
# Исключение значений
не_москвичи = df[~df['город'].isin(['Москва'])]
Сравнение методов фильтрации
| Метод | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
| Булевые маски | Гибкость, понятная логика | Громоздкий код при сложных условиях | Для несложных условий фильтрации |
| .loc | Интуитивный доступ по меткам, поддержка условий | Зависит от корректности имен/меток | Когда важны имена индексов и столбцов |
| .iloc | Быстрый доступ по позициям | Неявный код, сложно отслеживать что выбирается | Когда нужен доступ по числовым индексам |
| .query | Компактный и читаемый код | Ограниченная гибкость, строковый синтаксис | Для сложных условий или улучшения читаемости |
| .isin | Удобство при фильтрации по спискам | Ограничен проверкой вхождения в список | При необходимости фильтрации по набору значений |
Продвинутые техники фильтрации датафреймов
Когда базовые методы фильтрации уже освоены, пора переходить к продвинутым техникам, которые значительно расширяют возможности анализа данных и делают код более эффективным. Эти методы особенно полезны при работе с большими датасетами. 🚀
Фильтрация по строковым методам
Pandas предоставляет мощные инструменты для фильтрации по строкам с помощью методов str:
# Создаём пример датафрейма
df = pd.DataFrame({
'имя': ['Анна Иванова', 'Иван Петров', 'Мария Сидорова', 'Алексей Козлов'],
'email': ['anna@mail.ru', 'ivan@gmail.com', 'maria@yandex.ru', 'alex@gmail.com'],
'комментарий': ['Отличный продукт!', 'Требуется доработка', 'Не понравилось', 'Хорошо, но дорого']
})
# Поиск по подстроке
gmail_users = df[df['email'].str.contains('gmail')]
# Поиск с регулярными выражениями
import re
rus_email = df[df['email'].str.contains(r'@[a-z]+\.ru$', regex=True)]
# Фильтрация по началу строки
positive_comments = df[df['комментарий'].str.startswith('Отличный')]
# Фильтрация по длине строки
short_names = df[df['имя'].str.len() < 12]
Фильтрация по датам
Работа с временными рядами часто требует специальных методов фильтрации:
# Создаём датафрейм с датами
df_dates = pd.DataFrame({
'дата': pd.date_range('2023-01-01', periods=100, freq='D'),
'значение': np.random.randn(100).cumsum()
})
# Фильтрация по диапазону дат
january = df_dates[(df_dates['дата'] >= '2023-01-01') & (df_dates['дата'] <= '2023-01-31')]
# Использование dt аксессора
february_weekends = df_dates[
(df_dates['дата'].dt.month == 2) &
(df_dates['дата'].dt.dayofweek >= 5) # 5=суббота, 6=воскресенье
]
# Выборка конкретных дней недели
mondays = df_dates[df_dates['дата'].dt.day_name() == 'Monday']
Фильтрация с помощью функций
Для сложных условий можно использовать функции и метод .apply():
# Определяем функцию фильтрации
def is_valid_record(row):
if row['город'] == 'Москва' and row['возраст'] > 30:
return True
elif row['город'] == 'Санкт-Петербург' and row['зарплата'] > 100000:
return True
return False
# Применяем функцию для фильтрации
filtered_df = df[df.apply(is_valid_record, axis=1)]
# Используем lambda-функции для простых случаев
high_salary_by_age = df[df.apply(lambda x: x['зарплата'] > x['возраст'] * 2500, axis=1)]
Комбинированная фильтрация с агрегацией
Часто требуется фильтровать группы строк на основе агрегированных значений:
# Создаём датафрейм с продажами
sales = pd.DataFrame({
'дата': pd.date_range('2023-01-01', periods=100, freq='D'),
'продавец': np.random.choice(['Иван', 'Мария', 'Алексей', 'Елена'], 100),
'сумма': np.random.randint(1000, 10000, 100)
})
# Находим продавцов с суммой продаж выше среднего
avg_sales = sales.groupby('продавец')['сумма'].transform('mean')
top_sellers = sales[sales['сумма'] > avg_sales]
# Фильтруем только те дни, когда сумма продаж была выше среднедневной
daily_avg = sales.groupby('дата')['сумма'].transform('mean')
good_days = sales[sales['сумма'] > daily_avg]
Александра Петрова, ведущий аналитик данных
Работая с большим проектом в e-commerce, я столкнулась с задачей анализа поведения покупателей. Нам нужно было найти "спящих клиентов" — тех, кто ранее активно совершал покупки, но перестал это делать в последние 3 месяца.
Изначально я пыталась применять простые фильтры, но они не учитывали всей динамики поведения. Прорыв произошел, когда я применила комбинацию продвинутых фильтров с временными рядами и агрегацией.
Мы создали RFM-сегментацию, используя сложные фильтры pandas:
PythonСкопировать код# Находим последнюю дату покупки для каждого клиента last_purchase = df.groupby('customer_id')['date'].max() # Определяем "спящих" клиентов sleeping_date = today – pd.Timedelta(days=90) sleeping = df[df['customer_id'].isin( last_purchase[last_purchase < sleeping_date].index )] # Из них выбираем ранее активных high_value = sleeping.groupby('customer_id')['amount'].sum() > 15000 sleeping_vips = sleeping[sleeping['customer_id'].isin( high_value[high_value].index )]После запуска таргетированной кампании по реактивации этого сегмента, конверсия составила 23%, что в 3 раза выше стандартных показателей. Ключом к успеху стало именно умение комбинировать разные методы фильтрации в pandas.
Эффективные стратегии работы с датафреймами pandas
Простого знания методов создания и фильтрации недостаточно для эффективной работы с pandas. Важно применять правильные стратегии и паттерны, которые сделают ваш код более производительным, читаемым и поддерживаемым. Рассмотрим ключевые стратегии для опытных аналитиков данных. ⚡
Метод цепочек (method chaining)
Вместо множества отдельных операций с промежуточным сохранением, объединяйте методы в цепочки:
# Неоптимальный подход с промежуточными переменными
df = pd.read_csv('data.csv')
df = df.drop(['column1', 'column2'], axis=1)
df = df[df['value'] > 0]
df = df.sort_values('date')
df = df.reset_index(drop=True)
# Оптимальный подход с цепочкой методов
df = (pd.read_csv('data.csv')
.drop(['column1', 'column2'], axis=1)
.query('value > 0')
.sort_values('date')
.reset_index(drop=True))
Векторизация вместо циклов
Pandas оптимизирован для векторных операций. Избегайте циклов, используя встроенные методы:
# Неоптимальный подход с циклом
for i in range(len(df)):
df.loc[i, 'new_column'] = df.loc[i, 'value1'] + df.loc[i, 'value2']
# Оптимальный векторизованный подход
df['new_column'] = df['value1'] + df['value2']
# Векторизация сложных вычислений
df['category'] = np.where(df['value'] > 100, 'high',
np.where(df['value'] > 50, 'medium', 'low'))
Оптимизация памяти
При работе с большими датасетами важно оптимизировать использование памяти:
# Преобразование типов для экономии памяти
df_optimized = df.copy()
for col in df_optimized.select_dtypes(include=['int']).columns:
df_optimized[col] = pd.to_numeric(df_optimized[col], downcast='integer')
for col in df_optimized.select_dtypes(include=['float']).columns:
df_optimized[col] = pd.to_numeric(df_optimized[col], downcast='float')
# Категориальные данные
df_optimized['city'] = df_optimized['city'].astype('category')
# Использование chunksize для больших файлов
chunks = []
for chunk in pd.read_csv('large_file.csv', chunksize=10000):
# Обработка каждого фрагмента
filtered_chunk = chunk[chunk['value'] > 0]
chunks.append(filtered_chunk)
# Объединение результатов
result = pd.concat(chunks)
Методы .pipe() для создания конвейеров обработки
Метод .pipe() позволяет создавать чистые конвейеры обработки данных:
def remove_outliers(df, column, lower=0.01, upper=0.99):
"""Удаляет выбросы по указанному столбцу."""
q_low = df[column].quantile(lower)
q_high = df[column].quantile(upper)
return df[(df[column] >= q_low) & (df[column] <= q_high)]
def add_date_features(df, date_column):
"""Добавляет признаки на основе даты."""
df = df.copy()
df['year'] = df[date_column].dt.year
df['month'] = df[date_column].dt.month
df['day_of_week'] = df[date_column].dt.dayofweek
return df
# Использование pipe для создания конвейера обработки
processed_df = (pd.read_csv('sales.csv', parse_dates=['date'])
.pipe(remove_outliers, column='sales_amount')
.pipe(add_date_features, date_column='date')
.query('sales_amount > 0')
)
Эффективная фильтрация больших датафреймов
Для больших датафреймов оптимизируйте фильтрацию:
- Используйте индексы для ускорения фильтрации по часто используемым столбцам:
df.set_index('frequently_filtered_column') - Применяйте query() с параметром engine='numexpr' для ускорения:
df.query('value > 100', engine='numexpr') - Фильтруйте ранние этапы обработки, чтобы уменьшить объем данных в конвейере
- Используйте метод eval() для вычисления сложных выражений:
df.eval('total = price * quantity')
Практические советы по стилю кода
- Используйте явные имена переменных: не df1, df2, а customersdf, salesdf
- Добавляйте комментарии к сложным фильтрам и трансформациям
- Разбивайте длинные цепочки методов на несколько строк для читаемости
- Создавайте функции для повторяющихся операций фильтрации и трансформации
- Используйте контекстные переменные для временного изменения настроек:
with pd.option_context('display.max_rows', 100):
print(df)
Освоение создания и фильтрации датафреймов в pandas — это не просто набор технических знаний, а фундаментальный навык, открывающий дверь в мир эффективного анализа данных. Применяя изученные методы, вы сможете уверенно обрабатывать любые наборы данных, от простых таблиц до сложных многомерных структур. Главное помнить: мастерство приходит с практикой — экспериментируйте с разными подходами, создавайте свои конвейеры обработки и постепенно вырабатывайте свой стиль работы с pandas. И тогда из хаоса данных всегда будут появляться ясные, ценные инсайты.
Читайте также
- Топ-10 источников датасетов для машинного обучения: полное руководство
- Kaggle: как покорить Эверест машинного обучения для новичков
- Рекомендательные системы: как они работают и почему без них никуда
- 5 проверенных методов создания случайных массивов в Python
- Топ-10 онлайн-инструментов для поиска закономерностей в данных
- Matplotlib для Python: секреты создания профессиональных графиков
- Как сохранить JSON в файл на Python: руководство с примерами кода
- [Как увеличить глубину рекурсии в Python: 5 проверенных методов
Bard: RecursionError в Python: 5 проверенных методов увеличения глубины](/python/kak-uvelichit-glubinu-rekursii-v-python/)


