Самый частый вопрос к таблице начинается со слов «найди строки, где…»: где цена выше 2000, где город — Казань, где купили больше пяти штук. Это фильтрация — отбор строк по условию. Она делается в два шага.
Шаг первый: маска
Сравним столбец с числом. Как и арифметика, сравнение выполняется для каждого значения:
import pandas as pd
orders = pd.read_csv("data/shop_orders.csv")
orders["price"] > 30000 True
1 False
2 False
3 False
4 False
...
2443 False
2444 False
2445 False
2446 False
2447 False
Name: price, Length: 2448, dtype: boolПолучился Series из True и False с типом bool — по одному ответу на каждую строку. Такой Series
называют маской: True — строка подходит, False — нет. Сравнивать можно всеми операторами Python:
>, >=, <, <=, == (равно), != (не равно).
Шаг второй: маска в скобках
Если передать маску в квадратные скобки таблицы, останутся только строки, где в маске True:
orders[orders["price"] > 3000].head()| order_id | date | customer_id | city | channel | category | product | price | quantity | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 10001 | 2025-01-01 | C095 | Москва | маркетплейс | Аксессуары | Кофемолка ручная | 3200 | 2 |
| 7 | 10005 | 2025-01-02 | C033 | Казань | маркетплейс | Аксессуары | Кофемолка ручная | 3200 | 2 |
| 218 | 10135 | 2025-01-28 | C185 | Санкт-Петербург | приложение | Аксессуары | Кофемолка ручная | 3200 | 1 |
| 348 | 10217 | 2025-02-16 | C195 | Москва | сайт | Аксессуары | Кофемолка ручная | 3200 | 2 |
| 661 | 10424 | 2025-04-03 | C219 | Екатеринбург | приложение | Аксессуары | Кофемолка ручная | 3200 | 2 |
Обратите внимание на индекс слева: 0, 7, 218… Строки сохранили свои метки — об этом шла речь в прошлом уроке.
Обычно оба шага пишут в одну строку, как выше. Но маску можно сохранить в переменную — так код читается легче, а маску можно использовать повторно:
is_tea = orders["category"] == "Чай"
tea = orders[is_tea]
print(len(tea))
print(tea["price"].mean())682 381.1143695014663
Сохраните в expensive строки таблицы orders, где цена строго больше 2000, а в n_expensive — сколько
таких строк.
orders["price"] > 2000; подставьте её в orders[...].len(...).Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
expensive = ...
n_expensive = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
expensive = orders[orders["price"] > 2000]
n_expensive = len(expensive)Считаем по маске
Если нужны не сами строки, а их количество, таблицу можно не фильтровать. В вычислениях True считается
единицей, False — нулём. Поэтому сумма маски — сколько строк подошло, а среднее — какая это доля:
many = orders["quantity"] >= 5
print(many.sum())
print(many.mean())168 0.06862745098039216
168 строк — 6.9 % таблицы.
Сохраните в is_moscow маску: True у строк, где город — Москва. Затем в n_moscow — число таких строк,
а в share_moscow — их долю среди всех строк.
== — два знака. Один знак = — это присваивание.is_moscow.sum(), доля — is_moscow.mean().Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
is_moscow = ...
n_moscow = ...
share_moscow = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
is_moscow = orders["city"] == "Москва"
n_moscow = is_moscow.sum()
share_moscow = is_moscow.mean()Несколько условий
Условия соединяют операторами:
| Оператор | Значит | Строка подходит, если |
|---|---|---|
& |
и | выполнены оба условия |
| |
или | выполнено хотя бы одно |
~ |
не | условие не выполнено |
Каждое условие берут в круглые скобки:
orders[(orders["city"] == "Новосибирск") & (orders["price"] > 3000)]| order_id | date | customer_id | city | channel | category | product | price | quantity | |
|---|---|---|---|---|---|---|---|---|---|
| 1143 | 10731 | 2025-06-11 | C011 | Новосибирск | маркетплейс | Аксессуары | Кофемолка ручная | 3200 | 1 |
| 1378 | 10893 | 2025-07-25 | C121 | Новосибирск | приложение | Аксессуары | Кофемолка ручная | 3200 | 2 |
site_or_app = (orders["channel"] == "сайт") | (orders["channel"] == "приложение")
print(site_or_app.sum())
print((~site_or_app).sum())1821 627
Привычные and, or, not здесь не работают. Они ждут одно значение True или False, а получают
целый столбец таких значений:
orders[(orders["channel"] == "сайт") and (orders["price"] > 3000)]ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Скобки обязательны, потому что & и | выполняются раньше сравнений — как умножение раньше сложения.
Без скобок Python сначала вычислит "сайт" & orders["price"], что бессмысленно:
orders[orders["channel"] == "сайт" & orders["price"] > 3000]TypeError: Cannot perform 'rand_' with a dtyped [int64] array and scalar of type [bool]
Сохраните в kazan_big строки, где город — Казань и количество не меньше 5.
&.>= 5.Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
kazan_big = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
kazan_big = orders[(orders["city"] == "Казань") & (orders["quantity"] >= 5)]Что выведет
print((~(orders["channel"] == "сайт")).sum() == (orders["channel"] != "сайт").sum())?
~ переворачивает маску: «не равно сайту». != значит то же самое. Обе маски отмечают одни и те же строки, значит, и суммы равны.Назовём строку особой, если цена товара не ниже 2000 или количество не меньше 8. Сохраните в special
все особые строки, а в ordinary — все остальные.
| между двумя условиями в скобках.~. Удобно сначала сохранить маску в переменную.Заготовка упражнения обновилась с тех пор, как вы сохранили свой код.
Вернуть заготовку? Ваш код в этом упражнении будет удалён.
special = ...
ordinary = ...Упражнение пока не решено, поэтому для ячеек ниже выполнено эталонное решение — ваш код не изменён.
special = orders[(orders["price"] >= 2000) | (orders["quantity"] >= 8)]
ordinary = orders[~((orders["price"] >= 2000) | (orders["quantity"] >= 8))]Метод all() у маски отвечает одним True или False: во всех ли строках условие выполнено. Им удобно
проверять себя после фильтрации — например, что в таблице tea из примера выше действительно только чай:
print((tea["category"] == "Чай").all())
print((orders["price"] >= 150).all())
print((orders["quantity"] >= 2).all())True True False
Итоги
- Сравнение столбца даёт маску — Series из
TrueиFalse. таблица[маска]оставляет строки, гдеTrue; метки строк сохраняются.маска.sum()— сколько строк подходит,маска.mean()— какая доля.&— и,|— или,~— не; каждое условие в скобках;and,or,notне работают.