pandas: устройство, выборка и изменение таблиц

Выборка столбцов и строк: [], loc и iloc без цепочной индексации

Содержание курса

loc — выборка и фильтрация по меткам и булевым условиям

Оператор [] позволяет выбирать столбцы, но добраться до конкретных строк или ячеек через него удобно только в простейших случаях. Для полноценного доступа по строкам и ячейкам в pandas есть два инструмента: loc и iloc. Разберём loc — он работает с метками индекса.

Одна строка и одна ячейка

import pandas as pd

df = pd.DataFrame({
    'name':  ['Анна', 'Борис', 'Вера', 'Григорий'],
    'score': [85, 92, 78, 95],
    'city':  ['Москва', 'Казань', 'Москва', 'Уфа']
}, index=['a', 'b', 'c', 'd'])

print(df.loc['b'])
# name     Борис
# score       92
# city    Казань
# Name: b, dtype: object

print(df.loc['b', 'score'])  # 92

df.loc['b'] возвращает Series — всё, что лежит в строке с меткой 'b'. df.loc['b', 'score'] — скалярное значение конкретной ячейки. Первый аргумент — метка строки, второй — метка столбца.

Срез по меткам

print(df.loc['a':'c'])
#       name  score    city
# a     Анна     85  Москва
# b    Борис     92  Казань
# c     Вера     78  Москва

Важное отличие от обычного среза Python: обе границы включаются. df.loc['a':'c'] вернёт строки 'a', 'b' и 'c' — включая 'c'. Это поведение специфично для loc и часто удивляет тех, кто привык к list[0:2], где правая граница не входит в результат.

Фильтрация булевой маской

Вместо метки строки в loc можно передать булевый Series той же длины, что и индекс DataFrame:

mask = df['score'] >= 90
print(mask)
# a    False
# b     True
# c    False
# d     True
# Name: score, dtype: bool

print(df.loc[mask])
#       name  score          city
# b    Борис     92        Казань
# d  Григорий     95           Уфа

df['score'] >= 90 сравнивает каждое значение и возвращает Series из True/False с теми же метками. df.loc[mask] оставляет только строки, где значение маски — True.

Комбинирование условий

Если условий несколько, каждое оборачивается в скобки, и между ними ставятся & (и) или | (или):

combined = df.loc[(df['score'] >= 90) & (df['city'] == 'Казань')]
print(combined)
#     name  score    city
# b  Борис     92  Казань

Скобки вокруг каждого условия обязательны: без них оператор & применяется раньше, чем >= или ==, и Python выбрасывает ошибку.

Маска + столбец

Вторым аргументом loc можно сразу указать столбец — тогда результат будет не DataFrame, а Series нужного столбца по отфильтрованным строкам:

print(df.loc[mask, 'name'])
# b      Борис
# d    Григорий
# Name: name, dtype: object

Это удобно, когда нужна не вся таблица, а одна колонка после фильтрации — например, чтобы получить список имён с высокими оценками.

В итоге loc покрывает всё, что касается доступа через метки: конкретная строка, ячейка, диапазон строк, произвольный фильтр. Следующий шаг — iloc, который делает то же самое, но через целочисленные позиции, не зависящие от меток индекса.