2025, Nov 21 09:01

Индексирование в pandas: когда использовать [], loc и iloc

Разбираем индексирование в pandas DataFrame: чем отличаются [], loc и iloc, как выбирать по меткам и позициям, избегать ошибок KeyError/IndexError и писать код.

pandas предлагает три способа индексировать DataFrame: квадратные скобки, loc и iloc (раньше ещё был ix). То, что сначала кажется избыточным, — результат ранних архитектурных решений, определивших поведение выборки. Понимание этих решений снимает путаницу между доступом по меткам и по позициям и помогает писать предсказуемый, читаемый код.

Обзор проблемы

Корень путаницы в том, что квадратные скобки для DataFrame — это не двумерный слайсер. Скобки в первую очередь выбирают нижестоящий по размерности срез, то есть отдельный столбец. Параллельно pandas делает упор на объекты Index (метки), а не на целочисленные позиции, хотя значения меток строк по умолчанию — числовые. Из‑за числовых меток доступ по меткам выглядит как доступ по позициям, хотя это разные вещи.

Пример кода: откуда берётся путаница

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

import pandas as pd

frame = pd.DataFrame({"c1": [10, 20, 30], "c2": [40, 50, 60]}, index=[0, 1, 2])

# Квадратные скобки в первую очередь выбирают один столбец (срез меньшей размерности)
column_series = frame["c1"]

# Доступ по меткам через loc: число 0 здесь — это метка
row_by_label = frame.loc[0]

# Доступ по позициям через iloc: число 0 здесь — это позиция
row_by_position = frame.iloc[0]

На первый взгляд они взаимозаменяемы, но правила разные. С loc вы обращаетесь к меткам; с iloc — к целочисленным позициям. Когда у строк метки по умолчанию числовые, граница размывается, из‑за чего код становится неоднозначным, если не обозначить намерение явно.

Что происходит на самом деле

Текущее поведение объясняют два архитектурных решения. Во‑первых, квадратные скобки задуманы для извлечения данных меньшей размерности, а не для двумерного слайсинга. Иначе говоря, для DataFrame оператор скобок адресует Series по имени столбца:

«основная функция индексирования с помощью [] — выбор срезов меньшей размерности», то есть для датафреймов df[colname] должен «возвращать серию, соответствующую colname».

Во‑вторых, в pandas объекты Index с поддержкой меток — центральный механизм выборки и выравнивания. Метки — это хешируемые ключи, а не позиции. Функции, работающие с метками, выбрасывают KeyError при отсутствии ключа; iloc, который специально избегает меток, выбрасывает IndexError при выходе позиции за границы. Поскольку метки строк по умолчанию числовые, пользователи легко смешивают метки и позиции. Один из способов убрать неоднозначность — всегда проводить «намерение меток» через объект Index, но семантика меток была встроена прямо в DataFrame через loc, делая намерение явным на уровне API.

Решение: явно разделяйте метки и позиции

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

import pandas as pd

grid = pd.DataFrame({"alpha": [1, 2, 3], "beta": [4, 5, 6]}, index=[0, 1, 2])

# Выбор столбца (срез меньшей размерности):
col_alpha = grid["alpha"]

# Выбор строк по меткам:
first_row_by_label = grid.loc[0]

# Выбор строк по позициям:
first_row_by_pos = grid.iloc[0]

# Явная двумерная выборка по меткам:
rows_l = [0]
cols_l = ["alpha"]
label_cut = grid.loc[rows_l, cols_l]

# Явная двумерная выборка по позициям:
rows_p = [0]
cols_p = [0]
positional_cut = grid.iloc[rows_p, cols_p]

Если метки нет, выборка по меткам завершится ошибкой ключа; если позиция вне диапазона — позиционная выборка завершится ошибкой индекса. Эта ментальная модель позволяет сразу понимать, откуда берутся неожиданные ошибки при выборке.

Почему это важно

Из‑за этих решений DataFrame не рассматривается как чистая 2D‑матрица. Скобки оптимизированы под взгляд «словарь из Series», тогда как loc и iloc обеспечивают двумерную выборку с чётко различающейся семантикой. Со временем loc и iloc стали повседневными инструментами, а позиционное индексирование вновь набрало вес наравне с выборкой по меткам. Прямое опирание на числовые метки строк стало встречаться реже именно потому, что оно скрывает намерение.

Выводы

Старайтесь мыслить категориями «метки против позиций», а не «один аксессор на все случаи». Берите скобки, когда нужен столбец; loc — когда логика завязана на метки; iloc — когда нужны целочисленные позиции. Это соответствует эволюции pandas: оператор скобок — про выборку меньшей размерности, а loc и iloc — однозначные двумерные «рабочие лошадки». Такая привычка делает срезы данных понятными, предсказуемыми и удобными в сопровождении.