iloc vs loc в Pandas — в чём разница
Коротко
loc выбирает данные по меткам (именам строк и столбцов). iloc — по числовым позициям, как обычная индексация в Python. Главное различие: срезы в loc включают обе границы, а в iloc правая граница исключается.
loc — индексация по меткам
loc[строки, столбцы] использует метки индекса и имена столбцов. Если индекс — числа, loc всё равно работает по значениям индекса, а не по позициям.
import pandas as pd
df = pd.DataFrame({
'name': ['Анна', 'Борис', 'Вика', 'Глеб'],
'city': ['Москва', 'Питер', 'Казань', 'Москва'],
'salary': [80000, 120000, 95000, 110000]
}, index=['a', 'b', 'c', 'd'])
# Одна строка по метке
df.loc['b']
# name Борис
# city Питер
# salary 120000
# Несколько строк + конкретные столбцы
df.loc[['a', 'c'], ['name', 'salary']]
# name salary
# a Анна 80000
# c Вика 95000
# Срез по меткам — обе границы включены
df.loc['a':'c', 'name':'city']
# name city
# a Анна Москва
# b Борис Питер
# c Вика КазаньСрез 'a':'c' вернул строки a, b и c — правая граница включена. Это отличается от стандартного поведения Python.
iloc — индексация по позициям
iloc[строки, столбцы] работает как обычная индексация в Python: по целочисленным позициям, с исключением правой границы в срезах.
# Первая строка
df.iloc[0]
# name Анна
# city Москва
# salary 80000
# Строки 0, 1, 2 и столбцы 0, 2
df.iloc[0:3, [0, 2]]
# name salary
# a Анна 80000
# b Борис 120000
# c Вика 95000
# Последняя строка
df.iloc[-1]
# name Глеб
# city Москва
# salary 110000Срез 0:3 вернул строки с позициями 0, 1, 2 — позиция 3 исключена, как в обычном Python.
Булева фильтрация с loc
loc принимает булеву маску — это основной способ фильтрации данных:
# Все из Москвы
df.loc[df['city'] == 'Москва']
# name city salary
# a Анна Москва 80000
# d Глеб Москва 110000
# Зарплата > 100k, только имя и зарплата
df.loc[df['salary'] > 100000, ['name', 'salary']]
# name salary
# b Борис 120000
# d Глеб 110000С iloc булева фильтрация тоже работает, но столбцы указываются числами — менее читаемо.
at и iat — быстрый доступ к одному значению
Для скалярного доступа к одной ячейке есть at (по метке) и iat (по позиции). Они быстрее loc/iloc, когда нужно ровно одно значение.
# По метке
df.at['b', 'salary'] # 120000
# По позиции
df.iat[1, 2] # 120000На большом DataFrame разница в скорости заметна — at/iat в 5-10 раз быстрее loc/iloc для скалярного доступа.
Типичные ошибки
Путаница при числовом индексе
Когда индекс DataFrame — целые числа, loc и iloc ведут себя по-разному:
df2 = pd.DataFrame(
{'val': [10, 20, 30]},
index=[5, 10, 15]
)
df2.loc[5] # строка с индексом 5 → val: 10
df2.iloc[5] # IndexError — в DataFrame только 3 строки
df2.iloc[0] # первая строка → val: 10Это самый частый источник багов. Если индекс числовой — всегда явно используйте loc или iloc, не полагайтесь на df[5].
Off-by-one в срезах
# loc: включает обе границы
df.loc['a':'c'] # 3 строки: a, b, c
# iloc: правая граница исключена
df.iloc[0:3] # 3 строки: позиции 0, 1, 2
df.iloc[0:2] # 2 строки: позиции 0, 1Простое правило: iloc ведёт себя как range() в Python, loc — нет.
Практические примеры
# Топ-3 по зарплате
df_sorted = df.sort_values('salary', ascending=False)
top3 = df_sorted.iloc[:3]
# Обновить значение по условию
df.loc[df['city'] == 'Питер', 'salary'] = 130000
# Первые N строк конкретного столбца
first_five_names = df.iloc[:5, df.columns.get_loc('name')]Если вы хотите отработать индексацию на практике — откройте тренажёр и порешайте вопросы по Pandas.
Вопросы с собеседований
— В чём разница между loc и iloc? — loc выбирает данные по меткам индекса и именам столбцов, iloc — по числовым позициям. В срезах loc включает обе границы, iloc исключает правую — как стандартный Python.
— Что произойдёт, если индекс числовой и вы используете loc[1]? — loc ищет строку с меткой индекса 1, а не первую строку. Если метки 1 в индексе нет — KeyError. Для первой строки по позиции нужен iloc[0].
— Как выбрать строки по условию и конкретные столбцы?
— df.loc[df['col'] > 10, ['col_a', 'col_b']]. loc принимает булеву маску для строк и список имён столбцов.
— Чем at отличается от loc? — at возвращает скалярное значение одной ячейки и работает быстрее. loc может возвращать Series, DataFrame или скаляр — он более универсальный, но медленнее для точечного доступа.
— Можно ли использовать отрицательные индексы в iloc?
— Да. iloc[-1] — последняя строка, iloc[-3:] — последние три строки. В loc отрицательные индексы работают только если они есть в метках индекса.
FAQ
Можно ли обойтись без loc и iloc?
df['col'] вернёт столбец, df[df['col'] > 10] отфильтрует строки. Но для одновременного выбора строк и столбцов, для присвоения значений по условию и для однозначного кода loc/iloc обязательны.
Почему loc включает правую границу, а iloc — нет?
loc работает с метками, которые могут быть строками, датами, чем угодно — «следующий элемент после метки» не всегда определён. Поэтому обе границы включаются. iloc работает как стандартный Python (range, списки), где правая граница исключается.
Когда использовать at/iat вместо loc/iloc?
Когда точно нужно одно значение — например, в цикле или при точечном обновлении ячейки. В обычном анализе данных loc/iloc удобнее и читабельнее.
Что дальше
Разобрались с индексацией — переходите к группировке: groupby в Pandas. Если нужна шпаргалка по всем основным методам — шпаргалка по Pandas. Больше примеров вопросов — в каталоге, а отработать всё на практике можно в Python-тренажёре.