Нашли ошибку?
среднийpandas 3.0.6

where, mask, clip

Заменить значения по условию — выбросы, невозможные значения — и ограничить диапазоном.

Нужно знать:Фильтрация строк

Содержание статьи

Коротко

  • s.where(условие, другое) оставляет значения, где условие True, остальные заменяет (по умолчанию на NaN).
  • s.mask(условие, другое) — наоборот: заменяет, где условие True.
  • Замена может быть числом, Series или таблицей той же формы — значения берутся по меткам.
  • clip(lower, upper) ограничивает значения диапазоном; границы могут быть Series — свои для каждой строки.
  • Не путайте с np.where(условие, a, b): там выбирается одно из двух значений, а у where в pandas «другое» используется только там, где условие ложно.

Синтаксис

s.where(cond, other=nan)     # оставить, где cond
s.mask(cond, other=nan)      # заменить, где cond
s.clip(lower=None, upper=None)
np.where(cond, a, b)         # NumPy: массив из a или b

Параметры

ПараметрЧто делаетПо умолчанию
condусловие: булев Series / DataFrame или функция от объектаобязательный
otherна что заменить: значение, Series, DataFrame или функцияNaN
lower, upperв clip: границы — числа или SeriesNone
inplaceизменить на месте; в pandas 3 возвращает сам объектFalse

Примеры

Данные для примеровиспользуются во всех примерах ниже
temps = pd.Series([12.5, -45.0, 18.0, 99.0, 21.5], name="temp")   # два значения — сбой датчика
where: невозможные значения в NaN
temps.where(temps.between(-40, 50))          # оставить, где условие True; иначе NaN
Вывод
0    12.5
1     NaN
2    18.0
3     NaN
4    21.5
Name: temp, dtype: float64
mask: заменить то, что подходит под условие
temps.mask(temps > 50, 50)                    # заменить, где условие True
Вывод
0    12.5
1   -45.0
2    18.0
3    50.0
4    21.5
Name: temp, dtype: float64
Замена значениями другого Series
forecast = pd.Series([13.0, 11.0, 17.5, 20.0, 22.0])
temps.where(temps.between(-40, 50), forecast)   # замена значениями другого Series
Вывод
0    12.5
1    11.0
2    18.0
3    20.0
4    21.5
Name: temp, dtype: float64
По всей таблице
scores = pd.DataFrame({"math": [5, 2, 4], "phys": [3, 5, 1]})
scores.where(scores >= 3, 0)                  # по всей таблице
Вывод
   math  phys
0     5     3
1     0     5
2     4     0
clip: ограничить диапазоном
temps.clip(lower=-40, upper=50)               # ограничить диапазоном
Вывод
0    12.5
1   -40.0
2    18.0
3    50.0
4    21.5
Name: temp, dtype: float64
Свои границы для каждой строки
prices = pd.DataFrame({"low": [10, 20], "price": [5, 30], "high": [15, 25]})
prices["price"].clip(lower=prices["low"], upper=prices["high"])   # границы свои для каждой строки
Вывод
0    10
1    25
Name: price, dtype: int64

Подводные камни

where оставляет, а не заменяет

Логика обратная привычной: where(temps > 50, 50) заменит на 50 всё, что не больше 50. Для «заменить, если больше» — mask.

np.where возвращает массив

Результат np.where — массив NumPy без индекса. Чтобы получить Series, оберните: pd.Series(np.where(...), index=s.index).

np.where для Series
np.where(temps > 20, "тепло", "прохладно")    # NumPy: условие → одно из двух значений
Вывод
array(['прохладно', 'прохладно', 'прохладно', 'тепло', 'тепло'],
      dtype='<U9')