4 метода извлечения данных из DataFrame в Pandas: повысьте скорость
Для кого эта статья:
- Аналитики данных и специалисты в области обработки данных
- Студенты и профессионалы, изучающие Python и библиотеки для работы с данными
Люди, заинтересованные в повышении производительности и оптимизации кода в Pandas
Работа с данными в Python превращается из мучительного опыта в удовольствие, когда вы осваиваете правильные инструменты извлечения информации из DataFrame в Pandas. Как часто вы сталкивались с ситуацией, когда нужно было быстро достать конкретное значение из огромной таблицы данных? Этот навык — своего рода суперспособность аналитика, позволяющая одним элегантным выражением заменить десятки строк неоптимизированного кода. Разберемся с четырьмя методами — loc, iloc, at и iat — которые превратят вас из новичка в мастера точечного извлечения данных. 🚀
Если вы хотите уверенно работать не только с DataFrame, но и с полным стеком инструментов аналитика данных, обратите внимание на курс Профессия аналитик данных от Skypro. На программе вы не просто изучите Pandas на практических задачах, но и научитесь строить аналитические отчеты, визуализировать результаты и принимать решения на основе данных — навыки, за которые работодатели готовы платить от 90 000 рублей ежемесячно.
Основы доступа к данным в Pandas DataFrame
Прежде чем погружаться в методы извлечения данных, важно понимать, что такое DataFrame в Pandas. Это двумерная структура данных, напоминающая таблицу в Excel или SQL, с рядами (строками) и колонками (столбцами). Каждая ячейка в этой таблице содержит определенное значение, к которому можно получить доступ.
Создадим простой DataFrame для наших примеров:
import pandas as pd
import numpy as np
# Создаем тестовый DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50],
'C': [100, 200, 300, 400, 500]
})
# Устанавливаем индексы строк
df.index = ['row1', 'row2', 'row3', 'row4', 'row5']
print(df)
Результат выполнения кода:
| A | B | C | |
|---|---|---|---|
| row1 | 1 | 10 | 100 |
| row2 | 2 | 20 | 200 |
| row3 | 3 | 30 | 300 |
| row4 | 4 | 40 | 400 |
| row5 | 5 | 50 | 500 |
В Pandas существует несколько способов получить доступ к конкретной ячейке DataFrame:
- df[column][row] – базовый способ, но не самый эффективный
- df.loc[row, column] – доступ по метке (label-based)
- df.iloc[rowposition, columnposition] – доступ по позиции (position-based)
- df.at[row, column] – оптимизированный доступ по метке для одиночной ячейки
- df.iat[rowposition, columnposition] – оптимизированный доступ по позиции для одиночной ячейки
Каждый из этих методов имеет свои особенности, преимущества и ограничения. Давайте разберем их подробнее. 📊

Метод loc[] для точного извлечения значений
Метод loc[] используется для доступа к данным по меткам индексов и колонок. Это один из наиболее гибких методов, так как позволяет обращаться к данным через их метки, а не через числовые позиции.
Синтаксис loc[] выглядит следующим образом:
# Получение значения из ячейки на пересечении 'row2' и 'B'
value = df.loc['row2', 'B']
print(value) # Выведет: 20
# Получение всей строки 'row3'
row = df.loc['row3']
print(row)
# Получение нескольких строк и столбцов
subset = df.loc[['row1', 'row3'], ['A', 'C']]
print(subset)
# Использование булевой маски
mask = df['A'] > 3
filtered = df.loc[mask]
print(filtered)
Михаил Соколов, старший аналитик данных
Мой клиент — крупная розничная сеть — столкнулся с проблемой анализа данных о продажах по регионам. Руководитель BI-отдела жаловался на медленную работу скриптов при извлечении информации из огромных таблиц, а аналитики тратили больше времени на ожидание результатов, чем на их интерпретацию.
Когда я изучил их код, оказалось, что большинство аналитиков использовали базовый подход с двойной индексацией:
data[column][row]. При работе с таблицей в 3 миллиона строк это создавало серьезные задержки. Мы провели рефакторинг скриптов, заменив этот подход наloc[]для фильтрации данных по условиям и меткам.Результат превзошел ожидания: скорость выполнения запросов увеличилась в 4 раза. Особенно эффективным оказалось использование логических масок вида
df.loc[df['Region'] == 'Москва', 'Sales']— это позволило не только ускорить обработку, но и сделать код более читаемым для команды.
Преимущества метода loc[]:
- Интуитивно понятный синтаксис, особенно если у вас есть осмысленные метки индексов
- Поддержка срезов (slicing) с метками
- Возможность использования булевых масок для фильтрации данных
- Подходит для извлечения как одного значения, так и блоков данных
Однако у метода loc[] есть и некоторые ограничения:
- Если запрашиваемой метки не существует, возникает KeyError
- При работе с очень большими таблицами метод может быть не таким быстрым, как специализированные методы для одиночных ячеек
Также важно помнить, что при использовании loc[] со срезами, в отличие от обычной индексации в Python, включаются и начальная, и конечная метка. Например, df.loc['row1':'row3'] вернет строки row1, row2 и row3. 🔍
Метод iloc[] для позиционного доступа к элементам
В отличие от loc[], метод iloc[] (integer location) работает исключительно с целочисленными позициями, а не с метками. Это делает его идеальным для ситуаций, когда вы знаете точное положение нужных данных в DataFrame.
# Получение значения из ячейки в позиции [1, 1] (второй ряд, второй столбец)
value = df.iloc[1, 1]
print(value) # Выведет: 20
# Получение всей второй строки
row = df.iloc[1]
print(row)
# Получение нескольких строк и столбцов по их позициям
subset = df.iloc[[0, 2], [0, 2]]
print(subset)
# Использование срезов
slice_df = df.iloc[1:3, 0:2]
print(slice_df)
Метод iloc[] особенно полезен, когда:
- Вы работаете с данными, где индексы не имеют смысловой нагрузки
- Вам нужно выполнить итерацию по DataFrame построчно или по столбцам
- Необходимо получить n-й элемент независимо от его фактической метки
- Вы импортировали данные без установки специфических индексов
| Операция | loc[] | iloc[] |
|---|---|---|
| Тип индексации | По меткам | По позициям |
| Обработка срезов | Включительно | Исключительно |
| При несуществующем индексе | KeyError | IndexError |
| Поддержка булевых масок | Да | Да |
| Работа с MultiIndex | Поддерживает все уровни | Только позиционный доступ |
| Производительность на больших DF | Хорошая | Хорошая |
Важное отличие iloc[] от loc[] в обработке срезов: в iloc[] конечный индекс не включается в результат, что соответствует стандартному поведению Python. Например, df.iloc[0:2] вернет только строки с индексами 0 и 1 (первые две строки).
Ошибки, которых стоит избегать при работе с iloc[]:
- Попытка доступа к индексу, выходящему за границы DataFrame (например, если DataFrame содержит 5 строк, запрос
df.iloc[10]вызовет IndexError) - Использование строковых меток вместо позиций (например,
df.iloc['row1']вызовет TypeError) - Смешивание логики позиционного доступа и доступа по меткам (иногда в коде путают
loc[]иiloc[], что приводит к неочевидным ошибкам)
Выбор между loc[] и iloc[] зависит от контекста задачи и от того, как организованы ваши данные. Для работы с конкретными строками по их логическим идентификаторам используйте loc[], а для алгоритмической обработки с циклами и итерациями — iloc[]. 🧩
Оптимизация производительности с методами at и iat
Когда речь заходит о максимальной производительности при доступе к отдельным ячейкам DataFrame, Pandas предлагает специализированные методы at и iat. Эти методы оптимизированы для доступа к единичным ячейкам и работают значительно быстрее, чем их более общие аналоги loc и iloc.
Рассмотрим, как использовать эти методы:
# Метод at для доступа к одиночной ячейке по метке
value_at = df.at['row2', 'B']
print(value_at) # Выведет: 20
# Метод iat для доступа к одиночной ячейке по позиции
value_iat = df.iat[1, 1]
print(value_iat) # Выведет: 20
# Изменение значения с помощью at
df.at['row3', 'A'] = 999
print(df)
# Изменение значения с помощью iat
df.iat[0, 2] = 999
print(df)
Алексей Карпов, технический директор отдела аналитики
В нашем проекте мы столкнулись с серьезной проблемой производительности. Наш алгоритм обрабатывал финансовые данные, выполняя миллионы обращений к отдельным ячейкам DataFrame размером 500,000 × 100.
Первоначальная реализация использовала стандартный метод loc:
PythonСкопировать кодfor i in range(iterations): result += df.loc[rows[i], cols[i]]Когда я заменил loc на at:
PythonСкопировать кодfor i in range(iterations): result += df.at[rows[i], cols[i]]Время выполнения алгоритма сократилось с 87 секунд до 12 секунд — ускорение более чем в 7 раз!
Это был переломный момент для нашей команды. Мы провели полный аудит кодовой базы и заменили все обращения к единичным ячейкам на at/iat. Теперь та же обработка данных, которая раньше занимала часы, выполняется за минуты.
Давайте сравним производительность всех методов доступа к данным в DataFrame:
| Метод | Тип доступа | Относительная скорость | Оптимальное использование |
|---|---|---|---|
| df[col][row] | Цепочка индексации | Медленно (×0.5) | Не рекомендуется для частого использования |
| df.loc[row, col] | По метке | Средне (×1.0) | Выборка блоков данных по меткам |
| df.iloc[i, j] | По позиции | Средне (×1.1) | Выборка блоков данных по позициям |
| df.at[row, col] | По метке | Быстро (×10.0) | Доступ к одной ячейке по метке |
| df.iat[i, j] | По позиции | Очень быстро (×12.0) | Доступ к одной ячейке по позиции |
Эта разница в производительности особенно заметна при работе с большими DataFrame или при многократных обращениях к отдельным ячейкам внутри циклов.
Важные особенности методов at и iat:
- Они предназначены только для доступа к отдельным скалярным значениям, в отличие от loc и iloc, которые могут возвращать срезы и подмножества данных
- Методы at и iat не поддерживают булевую индексацию или срезы
- При работе в циклах с многократным обращением к отдельным ячейкам использование at и iat может ускорить код в несколько раз
- Эти методы также отлично подходят для обновления значений в DataFrame
Когда стоит использовать at и iat:
- Внутри циклов, где происходит многократное обращение к отдельным ячейкам
- В критичных к производительности участках кода
- При построчной обработке данных, где требуется доступ к определенным столбцам для каждой строки
- При обновлении значений в DataFrame на основе вычислений
Для максимальной производительности при работе с DataFrame стоит придерживаться следующего правила: используйте loc и iloc для выборки блоков данных, а at и iat — для доступа к отдельным ячейкам. 🚀
Практические сценарии извлечения данных в Pandas
Теперь, когда мы изучили различные методы доступа к данным, рассмотрим несколько практических сценариев, в которых эти методы могут быть особенно полезны.
Сценарий 1: Анализ временных рядов
При анализе временных рядов часто требуется доступ к данным по конкретным датам:
# Создаем DataFrame с временным индексом
dates = pd.date_range('20230101', periods=6)
df_ts = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
# Получаем данные за конкретную дату
specific_day = df_ts.loc['2023-01-03']
print(specific_day)
# Получаем значение конкретного показателя за конкретную дату
value_b_day2 = df_ts.at[dates[1], 'B']
print(f"Значение показателя B за {dates[1].date()}: {value_b_day2}")
Сценарий 2: Агрегация данных по группам
При работе с группированными данными можно эффективно извлекать и агрегировать значения:
# Создаем DataFrame с данными о продажах
sales_data = pd.DataFrame({
'Product': ['A', 'B', 'A', 'C', 'B', 'A'],
'Region': ['East', 'West', 'West', 'East', 'East', 'West'],
'Sales': [100, 200, 150, 300, 250, 180]
})
# Группируем данные по продукту и региону
grouped = sales_data.groupby(['Product', 'Region']).sum()
# Получаем продажи продукта A в регионе West
a_west_sales = grouped.loc[('A', 'West'), 'Sales']
print(f"Продажи продукта A в западном регионе: {a_west_sales}")
Сценарий 3: Фильтрация и обновление данных
Комбинация различных методов доступа может быть использована для сложных операций фильтрации и обновления:
# Создаем DataFrame с данными о сотрудниках
employees = pd.DataFrame({
'Name': ['John', 'Anna', 'Peter', 'Linda'],
'Department': ['IT', 'HR', 'IT', 'Finance'],
'Salary': [75000, 65000, 80000, 95000],
'Experience': [5, 3, 7, 10]
})
# Находим индексы сотрудников IT-отдела с опытом более 5 лет
it_exp_indices = employees[(employees['Department'] == 'IT') &
(employees['Experience'] > 5)].index
# Повышаем зарплату этим сотрудникам на 10%
for idx in it_exp_indices:
employees.at[idx, 'Salary'] *= 1.1
print(employees)
Сценарий 4: Оптимизация производительности при итеративной обработке
При необходимости выполнить операции для каждой ячейки большого DataFrame, разница в производительности между методами становится критичной:
# Создаем большой DataFrame для демонстрации
big_df = pd.DataFrame(np.random.randn(10000, 100))
# Не оптимально – использование loc в цикле
import time
start = time.time()
result = 0
for i in range(1000):
row, col = np.random.randint(0, 9999), np.random.randint(0, 99)
result += big_df.loc[row, col]
print(f"Время с loc: {time.time() – start} секунд")
# Оптимально – использование iat в цикле
start = time.time()
result = 0
for i in range(1000):
row, col = np.random.randint(0, 9999), np.random.randint(0, 99)
result += big_df.iat[row, col]
print(f"Время с iat: {time.time() – start} секунд")
В практических задачах выбор правильного метода доступа к данным может существенно влиять на производительность, читаемость и поддерживаемость кода. Вот несколько рекомендаций:
- Используйте
loc[]при работе с блоками данных по их осмысленным меткам или при сложной фильтрации - Применяйте
iloc[]при алгоритмической обработке данных, особенно когда важна позиция элемента - Выбирайте
atиiatпри частом обращении к отдельным ячейкам, особенно в циклах - Избегайте цепочки индексации
df[col][row], так как это создает временные объекты Series и замедляет выполнение - При работе с очень большими DataFrame рассматривайте возможность выборки нужных подмножеств данных перед выполнением интенсивных вычислений
Эффективное извлечение данных из DataFrame — это ключевой навык для любого аналитика или инженера данных, работающего с Python и Pandas. Овладение различными методами доступа позволит вам писать более элегантный, производительный и поддерживаемый код. 📈
Владение методами извлечения данных из Pandas DataFrame — фундаментальный навык, который разделяет начинающих и опытных аналитиков данных. Выбирайте loc для работы с осмысленными индексами и сложной фильтрации, iloc для алгоритмических операций по позиции, и методы at/iat для максимальной производительности при точечном доступе. Помните, что правильный инструмент не только ускоряет работу, но и делает ваш код более читаемым и понятным для коллег — качество, которое ценится не меньше скорости выполнения.