Создание и фильтрация датафреймов в pandas: руководство для новичков

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • начинающие аналитики данных
  • студенты и профессионалы, желающие улучшить навыки работы с pandas
  • специалисты, интересующиеся эффективными методами анализа данных в Python

    Когда впервые сталкиваешься с анализом данных в Python, библиотека pandas кажется непреодолимой стеной сложных функций и методов. Я помню свой первый день с pandas: десятки ошибок в коде, непонятные названия методов и полное отчаяние. Но стоило освоить создание и фильтрацию датафреймов — и внезапно открылся целый мир возможностей для работы с данными. Эта статья — ваш ключ к освоению фундаментальных навыков pandas, которые превратят хаос чисел в управляемые, логичные структуры. 📊

Хотите изучить pandas глубоко и системно? Курс Профессия аналитик данных от Skypro погружает в мир обработки данных через практические задачи. Вы не просто изучите pandas — вы научитесь создавать, фильтровать и трансформировать датафреймы на реальных проектах под руководством опытных аналитиков. В отличие от фрагментарных туториалов, курс даёт последовательную систему знаний, которая превратит вас в настоящего повелителя данных.

Создание датафреймов в pandas: 5 основных способов

Датафрейм — это двумерная структура данных в pandas, похожая на таблицу в Excel или SQL. Это ключевой инструмент для любого аналитика данных. Рассмотрим 5 основных способов создания датафреймов, от простейших до продвинутых.

Прежде всего, импортируем необходимые библиотеки:

Python
Скопировать код
import pandas as pd
import numpy as np

Способ 1: Создание из словаря

Самый простой способ — создать датафрейм из словаря Python, где ключи станут именами столбцов:

Python
Скопировать код
data = {
'Имя': ['Анна', 'Иван', 'Мария', 'Алексей'],
'Возраст': [28, 32, 25, 41],
'Город': ['Москва', 'Санкт-Петербург', 'Казань', 'Новосибирск']
}

df = pd.DataFrame(data)
print(df)

Способ 2: Создание из списков

Можно создать датафрейм из списка списков, указав имена столбцов отдельно:

Python
Скопировать код
data = [
['Анна', 28, 'Москва'],
['Иван', 32, 'Санкт-Петербург'],
['Мария', 25, 'Казань'],
['Алексей', 41, 'Новосибирск']
]

df = pd.DataFrame(data, columns=['Имя', 'Возраст', 'Город'])
print(df)

Способ 3: Создание из массива NumPy

Если ваши данные уже хранятся в виде NumPy массива:

Python
Скопировать код
data = np.array([
['Анна', 28, 'Москва'],
['Иван', 32, 'Санкт-Петербург'],
['Мария', 25, 'Казань'],
['Алексей', 41, 'Новосибирск']
])

df = pd.DataFrame(data, columns=['Имя', 'Возраст', 'Город'])
print(df)

Способ 4: Создание с помощью Series

Series — это одномерный массив с метками, который можно использовать для создания столбцов датафрейма:

Python
Скопировать код
name = pd.Series(['Анна', 'Иван', 'Мария', 'Алексей'])
age = pd.Series([28, 32, 25, 41])
city = pd.Series(['Москва', 'Санкт-Петербург', 'Казань', 'Новосибирск'])

df = pd.DataFrame({
'Имя': name,
'Возраст': age,
'Город': city
})
print(df)

Способ 5: Пустой датафрейм с последующим заполнением

Иногда требуется создать пустой датафрейм и заполнить его позже:

Python
Скопировать код
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) — один из самых распространенных форматов для хранения табличных данных:

Python
Скопировать код
# Базовое чтение 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):

Python
Скопировать код
# Чтение из Excel
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# Чтение нескольких листов
sheets = pd.read_excel('data.xlsx', sheet_name=None) # словарь с датафреймами

Чтение из SQL-баз данных

Pandas может напрямую читать данные из баз данных:

Python
Скопировать код
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 и веб-сервисах:

Python
Скопировать код
# Из 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)

Пример комплексной настройки датафрейма после импорта:

Python
Скопировать код
# Импорт данных
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 предлагает несколько мощных методов для отбора нужных строк и столбцов из датафреймов. 🔍

Фильтрация с помощью булевых масок

Самый гибкий способ фильтрации — использование булевых масок:

Python
Скопировать код
# Создаём пример датафрейма
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 используется для доступа к данным по метке (имени) строки или столбца:

Python
Скопировать код
# Выбор по индексу строки и имени столбца
df.loc[0, 'имя'] # Анна

# Выбор нескольких строк и столбцов
df.loc[0:2, ['имя', 'возраст']]

# Фильтрация строк с условиями
df.loc[df['город'] == 'Москва', ['имя', 'зарплата']]

Метод .iloc для фильтрации по позиции

Метод .iloc используется для доступа к данным по числовой позиции (как в обычном списке):

Python
Скопировать код
# Выбор по позиции строки и столбца
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() позволяет писать условия фильтрации в виде строки, что иногда удобнее для сложных запросов:

Python
Скопировать код
# Фильтрация с помощью query
москвичи = df.query("город == 'Москва'")

# Сложные условия
москвичи_или_богатые = df.query("город == 'Москва' or зарплата > 100000")

# Использование переменных с @
порог_зарплаты = 90000
высокооплачиваемые = df.query("зарплата > @порог_зарплаты")

Фильтрация с помощью .isin()

Метод .isin() позволяет проверять вхождение в список значений:

Python
Скопировать код
# Фильтрация по списку значений
крупные_города = ['Москва', 'Санкт-Петербург']
жители_крупных_городов = df[df['город'].isin(крупные_города)]

# Исключение значений
не_москвичи = df[~df['город'].isin(['Москва'])]

Сравнение методов фильтрации

Метод Преимущества Недостатки Когда использовать
Булевые маски Гибкость, понятная логика Громоздкий код при сложных условиях Для несложных условий фильтрации
.loc Интуитивный доступ по меткам, поддержка условий Зависит от корректности имен/меток Когда важны имена индексов и столбцов
.iloc Быстрый доступ по позициям Неявный код, сложно отслеживать что выбирается Когда нужен доступ по числовым индексам
.query Компактный и читаемый код Ограниченная гибкость, строковый синтаксис Для сложных условий или улучшения читаемости
.isin Удобство при фильтрации по спискам Ограничен проверкой вхождения в список При необходимости фильтрации по набору значений

Продвинутые техники фильтрации датафреймов

Когда базовые методы фильтрации уже освоены, пора переходить к продвинутым техникам, которые значительно расширяют возможности анализа данных и делают код более эффективным. Эти методы особенно полезны при работе с большими датасетами. 🚀

Фильтрация по строковым методам

Pandas предоставляет мощные инструменты для фильтрации по строкам с помощью методов str:

Python
Скопировать код
# Создаём пример датафрейма
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]

Фильтрация по датам

Работа с временными рядами часто требует специальных методов фильтрации:

Python
Скопировать код
# Создаём датафрейм с датами
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():

Python
Скопировать код
# Определяем функцию фильтрации
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)]

Комбинированная фильтрация с агрегацией

Часто требуется фильтровать группы строк на основе агрегированных значений:

Python
Скопировать код
# Создаём датафрейм с продажами
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)

Вместо множества отдельных операций с промежуточным сохранением, объединяйте методы в цепочки:

Python
Скопировать код
# Неоптимальный подход с промежуточными переменными
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 оптимизирован для векторных операций. Избегайте циклов, используя встроенные методы:

Python
Скопировать код
# Неоптимальный подход с циклом
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'))

Оптимизация памяти

При работе с большими датасетами важно оптимизировать использование памяти:

Python
Скопировать код
# Преобразование типов для экономии памяти
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() позволяет создавать чистые конвейеры обработки данных:

Python
Скопировать код
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
  • Добавляйте комментарии к сложным фильтрам и трансформациям
  • Разбивайте длинные цепочки методов на несколько строк для читаемости
  • Создавайте функции для повторяющихся операций фильтрации и трансформации
  • Используйте контекстные переменные для временного изменения настроек:
Python
Скопировать код
with pd.option_context('display.max_rows', 100): 
print(df)

Освоение создания и фильтрации датафреймов в pandas — это не просто набор технических знаний, а фундаментальный навык, открывающий дверь в мир эффективного анализа данных. Применяя изученные методы, вы сможете уверенно обрабатывать любые наборы данных, от простых таблиц до сложных многомерных структур. Главное помнить: мастерство приходит с практикой — экспериментируйте с разными подходами, создавайте свои конвейеры обработки и постепенно вырабатывайте свой стиль работы с pandas. И тогда из хаоса данных всегда будут появляться ясные, ценные инсайты.

Читайте также

Bard: RecursionError в Python: 5 проверенных методов увеличения глубины](/python/kak-uvelichit-glubinu-rekursii-v-python/)

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой метод в pandas позволяет создавать DataFrame из словаря?
1 / 5

Загрузка...