Pandas loc vs iloc: полное руководство с примерами на реальных данных | AiManual
AiManual Logo Ai / Manual.
15 Фев 2026 Гайд

Pandas: окончательное руководство по loc и iloc с примерами на реальном датасете

Разбираем loc и iloc в Pandas на примере реального датасета. Чем отличаются, когда использовать, частые ошибки и лучшие практики работы с DataFrame.

Почему loc и iloc — это не просто "два способа выбрать данные"

Каждый, кто начинает работать с Pandas, сталкивается с этой дилеммой: loc или iloc? На первый взгляд разница кажется минимальной — один использует метки, другой позиции. Но на практике неправильный выбор приводит к ошибкам, которые сложно отловить, особенно когда датасет меняется динамически.

Представьте: вы написали скрипт, который прекрасно работал на тестовых данных. Запускаете на продакшене — и получаете KeyError или IndexError. Потому что кто-то добавил строку в начало файла, и все ваши позиционные индексы съехали.

В Pandas 2.6.0 (актуально на февраль 2026) обе функции получили оптимизации производительности, но логика работы осталась прежней. Если вы до сих пор путаетесь — эта статья для вас.

Создаём реалистичный датасет для экспериментов

Давайте возьмём не абстрактные цифры, а что-то похожее на реальную задачу. Допустим, у нас данные о продажах в интернет-магазине за первую неделю февраля 2026:

import pandas as pd
import numpy as np

# Создаём датасет с продажами
np.random.seed(42)
dates = pd.date_range('2026-02-01', periods=7, freq='D')
data = {
    'order_id': [f'ORD-{i:04d}' for i in range(1001, 1008)],
    'customer_id': np.random.choice(['C001', 'C002', 'C003', 'C004', 'C005'], 7),
    'product': ['Ноутбук', 'Смартфон', 'Наушники', 'Планшет', 'Мышь', 'Клавиатура', 'Монитор'],
    'category': ['Электроника', 'Электроника', 'Аксессуары', 'Электроника', 'Аксессуары', 'Аксессуары', 'Электроника'],
    'price': [899.99, 599.50, 129.99, 449.00, 24.99, 89.99, 299.99],
    'quantity': [1, 1, 2, 1, 3, 2, 1],
    'discount': [0.1, 0.0, 0.15, 0.05, 0.2, 0.1, 0.0],
    'date': dates
}

df = pd.DataFrame(data)
df['total'] = df['price'] * df['quantity'] * (1 - df['discount'])

# Устанавливаем order_id как индекс (это важно!)
df.set_index('order_id', inplace=True)

print(df.head())

Получаем такой DataFrame:

order_idcustomer_idproductcategorypricequantitydiscountdatetotal
ORD-1001C004НоутбукЭлектроника899.9910.102026-02-01809.99
ORD-1002C002СмартфонЭлектроника599.5010.002026-02-02599.50

loc: когда метки важнее позиций

loc работает с метками индекса и названиями столбцов. Это как обращаться к человеку по имени, а не по номеру в списке.

1Базовый синтаксис loc

# Выбираем одну строку по метке индекса
single_row = df.loc['ORD-1003']
print(single_row['product'])  # Наушники

# Выбираем несколько строк по списку меток
multiple_rows = df.loc[['ORD-1001', 'ORD-1004', 'ORD-1007']]
print(multiple_rows.shape)  # (3, 8)

# Выбираем строки и столбцы
row_col = df.loc['ORD-1002', ['product', 'price', 'total']]
print(row_col)
💡
loc всегда использует квадратные скобки с двумя измерениями: [строки, столбцы]. Даже если вы выбираете одну строку, это всё равно двумерная операция.

2Срезы с loc — ловушка для новичков

Вот где начинается путаница. С loc срезы работают по-другому:

# Срез по меткам — ВКЛЮЧИТЕЛЬНЫЙ
slice_inclusive = df.loc['ORD-1002':'ORD-1005']
print(len(slice_inclusive))  # 4 строки (1002, 1003, 1004, 1005)

# Сравните с обычным Python срезом списка:
list_slice = ['a', 'b', 'c', 'd', 'e'][1:4]  # ['b', 'c', 'd'] - ИСКЛЮЧИТЕЛЬНЫЙ

# Срез по столбцам тоже работает
cols_slice = df.loc[:, 'product':'quantity']
print(cols_slice.columns.tolist())  # ['product', 'category', 'price', 'quantity']

Включительность срезов в loc — это одновременно и удобство, и источник ошибок. Если метки не отсортированы, срез вернёт пустой DataFrame без ошибки.

3Булева маска — самая мощная фича loc

Здесь loc показывает свою настоящую силу:

# Все заказы дороже 500 рублей
expensive = df.loc[df['total'] > 500]
print(expensive.index.tolist())  # ['ORD-1001', 'ORD-1002']

# Заказы из категории "Электроника" с количеством больше 1
electronics_multiple = df.loc[(df['category'] == 'Электроника') & (df['quantity'] > 1)]
print(electronics_multiple)  # Пусто — у нас нет таких

# Комбинируем с выбором столбцов
filtered_cols = df.loc[df['discount'] > 0, ['product', 'price', 'discount', 'total']]
print(filtered_cols)

Булевы маски — это то, что делает Pandas таким выразительным. Но есть нюанс: маска должна быть того же размера, что и DataFrame. Если вы создали маску на основе подмножества данных — получите ошибку.

iloc: когда позиции надёжнее меток

iloc работает с целочисленными позициями. Это как обращаться "третий человек в шеренге", неважно как его зовут.

4Базовый синтаксис iloc

# Первая строка (позиция 0)
first_row = df.iloc[0]
print(first_row.name)  # ORD-1001

# Последняя строка
last_row = df.iloc[-1]
print(last_row.name)  # ORD-1007

# Несколько строк по позициям
positions = df.iloc[[0, 2, 4]]
print(positions.index.tolist())  # ['ORD-1001', 'ORD-1003', 'ORD-1005']

# Строки и столбцы по позициям
subset = df.iloc[1:4, 0:3]  # Строки 1-3, столбцы 0-2
print(subset.columns.tolist())  # ['customer_id', 'product', 'category']

Важное отличие: срезы в iloc исключительные, как в обычном Python. df.iloc[1:4] вернёт строки с позициями 1, 2, 3. Не 4.

5Когда iloc незаменим

Есть ситуации, где iloc — единственный разумный выбор:

# 1. Когда нужны первые/последние N строк
first_three = df.iloc[:3]
last_two = df.iloc[-2:]

# 2. Когда индексы — не строки, а что-то сложное
# (хотя в нашем случае это строки, но представьте даты или составные ключи)

# 3. Когда вы делаете алгоритмическую обработку
for i in range(0, len(df), 2):  # Каждая вторая строка
    row = df.iloc[i]
    # Какая-то обработка

# 4. Когда метки индекса не уникальны (да, так бывает!)
df_duplicates = df.copy()
df_duplicates.index = ['A', 'B', 'A', 'C', 'D', 'E', 'F']  # Дублирующийся индекс
# df.loc['A'] вернёт ДВЕ строки
# df.iloc[0] и df.iloc[2] вернут разные строки

Реальная задача: анализ продаж по неделям

Давайте применим оба метода к практической задаче. У нас есть данные за неделю, нужно:

  1. Найти самый дорогой заказ
  2. Посчитать средний чек по категориям
  3. Выбрать все заказы со скидкой больше 10%
  4. Создать отчёт по первым трём дням
# 1. Самый дорогой заказ (используем loc для точности)
max_total_idx = df['total'].idxmax()  # Находим метку индекса максимального значения
most_expensive = df.loc[max_total_idx]
print(f"Самый дорогой заказ: {most_expensive['product']} за {most_expensive['total']:.2f} руб.")

# 2. Средний чек по категориям (здесь loc не нужен, но покажем для сравнения)
# Способ 1: Без loc/iloc
avg_by_category = df.groupby('category')['total'].mean()

# Способ 2: С использованием loc для фильтрации
electronics_avg = df.loc[df['category'] == 'Электроника', 'total'].mean()
accessories_avg = df.loc[df['category'] == 'Аксессуары', 'total'].mean()

# 3. Заказы со скидкой > 10% (идеально для loc с булевой маской)
big_discounts = df.loc[df['discount'] > 0.1]
print(f"Заказы со скидкой >10%: {len(big_discounts)} шт.")

# 4. Отчёт по первым трём дням (здесь iloc логичнее)
first_three_days = df.iloc[:3].copy()
first_three_days['discount_amount'] = first_three_days['price'] * first_three_days['quantity'] * first_three_days['discount']
print(first_three_days[['product', 'total', 'discount_amount']])

Типичные ошибки и как их избежать

Я видел эти ошибки в десятках проектов. Запомните их — сэкономите часы отладки.

ОшибкаПочему происходитКак исправить
KeyError при использовании loc с числомПытаетесь df.loc[0], но индекс — строкиИспользуйте df.iloc[0] или измените индекс
Пустой результат среза locМетки в срезе не отсортированыПроверьте df.index.is_monotonic_increasing
SettingWithCopyWarningИзменяете срез, а не оригиналИспользуйте .copy() или .loc[:, 'новая_колонка'] = ...
Несоответствие размеров маскиМаска создана для подмножества данныхУбедитесь, что mask.shape[0] == df.shape[0]

loc vs iloc: окончательный вердикт

После всего сказанного, вот простое правило:

  • Используйте loc когда работаете с конкретными метками, делаете фильтрацию по условиям, или когда ваша логика зависит от содержимого данных, а не от их позиции.
  • Используйте iloc когда нужны первые/последние N строк, когда делаете алгоритмическую обработку по позициям, или когда индексы ненадёжны (дублируются, меняются).

Но есть и третий путь: иногда лучше вообще не использовать ни loc, ни iloc напрямую. Например, для сложной фильтрации посмотрите 10 элегантных способов фильтрации Pandas DataFrame. А если работаете с огромными датасетами, возможно, вам пригодится техника streaming из Datasets.

Продвинутые трюки, о которых мало кто знает

Pandas постоянно развивается. Вот что появилось или стало стабильным в последних версиях:

# 1. Callable в loc (Pandas 2.1+)
# Можно передавать функцию для выбора строк
def high_value_orders(df):
    return df['total'] > df['total'].median()

high_value = df.loc[high_value_orders]

# 2. Поддержка типов в iloc (Pandas 2.2+)
# Теперь можно явно указывать типы возвращаемых данных
from pandas.api.types import is_numeric_dtype

numeric_cols = [i for i, col in enumerate(df.columns) if is_numeric_dtype(df[col])]
numeric_data = df.iloc[:, numeric_cols]

# 3. Оптимизация производительности (Pandas 2.6+)
# Обе функции теперь используют более эффективные алгоритмы
# Особенно заметно на больших DataFrame с MultiIndex
💡
Самый частый вопрос: "А что быстрее?" Ответ: это зависит. На маленьких данных разница незаметна. На больших — loc с булевыми масками обычно быстрее, потому что использует векторизацию. Но если вам действительно нужна производительность, измеряйте на своих данных, а не верьте общим советам.

Что делать, когда ничего не работает

Бывает такое: вы уверены, что код правильный, но loc или iloc возвращают не то, что ожидаете. Вот чек-лист:

  1. Проверьте тип индекса: print(type(df.index))
  2. Убедитесь, что индекс уникален: print(df.index.is_unique)
  3. Посмотрите на фактические метки: print(df.index.tolist()[:5])
  4. Проверьте, не изменился ли DataFrame после каких-то операций (особенно после группировок или слияний)
  5. Используйте df._is_view чтобы понять, работаете вы с view или копией

И последний совет: если вы часто путаете loc и iloc, возможно, проблема не в вас, а в дизайне индекса. Хорошо спроектированный индекс делает использование loc естественным. Плохой индекс заставляет постоянно использовать iloc и надеяться на удачу.

Кстати, если вы работаете с текстовыми данными и думаете, что Pandas — это сложно, попробуйте поработать с OLMocr 2 для чтения документов или LLM для чистки справочников. Тогда Pandas покажется райским садом простоты.

А теперь идите и напишите три строки кода с loc и три с iloc. Без практики эта статья — просто текст на экране.