Методы .mask()
и .where()
являются применением идиомы if/then
. К тому же, выбор значений из ряда с логическим вектором обычно возвращает подмножество данных Series
/DataFrame
. Чтобы гарантировать, что выходные данные выборки имеют ту же форму, что и исходные данные, можно использовать методы .mask()
и .where()
в Series
и DataFrame
.
DataFrame.mask()
- заменяет значение элемента DataFrame
если условие выполнилось;Series.mask()
- заменяет значение элемента Series
если условие выполнилось;DataFrame.where()
- заменяет значение элемента Series
если условие НЕ выполнилось;;Series.where()
- заменяет значение элемента DataFrame
если условие НЕ выполнилось;.mask()
и .where()
объектов Series
/DataFrame
.DataFrame.mask(cond, other=no_default, *, inplace=False, axis=None, level=None)
:Series.mask(cond, other=no_default, *, inplace=False, level=None)
:Методы DataFrame.mask()
и Series.mask()
заменяют значения элементов соответствующих объектов, в которых условие равно True
.
Эти методы являются применением идиомы if/then
. Для каждого элемента в вызывающем DataFrame
/Series
, если cond
равно False
, то используется его элемент, в противном случае используется соответствующий элемент из other
. Если ось other
не совпадает с осью cond
DataFrame
/Series
, то смещенные позиции индекса будут заполнены значением True
.
Принимаемые аргументы:
cond
- там, где cond
имеет значение False
, сохраняется исходное значение. Если True
, то заменяет соответствующим значением из other
. Если cond
является вызываемым объектом, то он вычисляется в Series
/DataFrame
и должен возвращать логический Series
/DataFrame
или массив. Вызываемый объект не должен изменять входные Series
/DataFrame
(хотя pandas
это не проверяет).other
- там, где cond
имеет значение True
, заменяются соответствующим значением из other
. Если other
является вызываемым объектом, он вычисляется в Series
/DataFrame
и должен возвращать скаляр или Series
/DataFrame
. Вызываемый объект не должен изменять входные Series
/DataFrame
(хотя pandas
не проверяет это). Если не указан, то записи будут заполнены соответствующим значением NULL
(np.nan
для dtypes
из numpy
, pd.NA
для расширений dtypes
).inplace=False
- следует ли выполнять операцию на месте с данными (не рекомендуется к использованию).axis=None
- при необходимости выравнивает данные по указанной оси. Для Series
этот аргумент не используется и по умолчанию равен 0.level=None
- уровень выравнивания при необходимостиDataFrame.where(cond, other=nan, *, inplace=False, axis=None, level=None)
:Series.where(cond, other=nan, *, inplace=False level=None)
:Методы DataFrame.where()
и Series.where()
заменяют значения элементов соответствующих объектов, в которых условие равно False
.
Эти методы являются применением идиомы if/then
. Для каждого элемента в вызывающем DataFrame
/Series
, если cond
равно True
, то используется его элемент, в противном случае используется соответствующий элемент из other
. Если ось other
не совпадает с осью cond
DataFrame
/Series
, то смещенные позиции индекса будут заполнены значением True
.
Принимаемые аргументы:
cond
- там, где cond
имеет значение False
, сохраняется исходное значение. Если True
, то заменяет соответствующим значением из other
. Если cond
является вызываемым объектом, то он вычисляется в Series
/DataFrame
и должен возвращать логический Series
/DataFrame
или массив. Вызываемый объект не должен изменять входные Series
/DataFrame
(хотя pandas
это не проверяет).other
- там, где cond
имеет значение True
, заменяются соответствующим значением из other
. Если other
является вызываемым объектом, он вычисляется в Series
/DataFrame
и должен возвращать скаляр или Series
/DataFrame
. Вызываемый объект не должен изменять входные Series
/DataFrame
(хотя pandas
не проверяет это). Если не указан, то записи будут заполнены соответствующим значением NULL
(np.nan
для dtypes
из numpy
, pd.NA
для расширений dtypes
).inplace=False
- следует ли выполнять операцию на месте с данными (не рекомендуется к использованию).axis=None
- при необходимости выравнивает данные по указанной оси. Для Series
этот аргумент не используется и по умолчанию равен 0.level=None
- уровень выравнивания при необходимостиСигнатура для DataFrame.where()
отличается от numpy.where()
. Грубо df1.where(m, df2)
эквивалентен np.where(m, df1, df2)
.
.mask()
и .where()
объектов Series
/DataFrame
Выбор значений из ряда с логическим вектором обычно возвращает подмножество данных. Для гарантии того, что выходные данные выборки имеют ту же форму, что и исходные данные, можно использовать метод .where()
или .mask()
в Series
и DataFrame
.
Чтобы вернуть только выбранные строки, нужно выполнить следующие действия.
>>> import pandas as pd >>> import numpy as np >>> s = pd.Series(np.arange(5), index=np.arange(5)[::-1], dtype='int64') >>> s # 4 0 # 3 1 # 2 2 # 1 3 # 0 4 # dtype: int64 >>> s[s > 0] # 3 1 # 2 2 # 1 3 # 0 4 # dtype: int64
Чтобы вернуть серию той же формы, что и оригинал:
>>> s.where(s > 0) # 4 NaN # 3 1.0 # 2 2.0 # 1 3.0 # 0 4.0 # dtype: float64
В отличие от Series
, выбор значений из DataFrame
с помощью логического вектора сохраняет форму входных данных (под капотом используется метод DataFrame.where()
).
>>> dates = pd.date_range('1/1/2000', periods=8) df = pd.DataFrame(np.random.randn(8, 4), index=dates, columns=['A', 'B', 'C', 'D']) # выбор данных с помощью логического вектора >>> df[df < 0] # A B C D # 2000-01-01 -0.044333 -0.051989 -1.947218 -0.677572 # 2000-01-02 -0.631469 NaN -1.573849 -0.853425 # 2000-01-03 NaN -0.272759 -0.577754 NaN # 2000-01-04 NaN NaN -0.179180 -0.147158 # 2000-01-05 -0.339024 -0.990385 NaN NaN # 2000-01-06 NaN -0.297956 NaN NaN # 2000-01-07 -0.131227 NaN NaN -1.202555 # 2000-01-08 NaN -1.957476 NaN -0.409341 # выбор данных с помощью метода `.where()` >>> df.where(df < 0) # A B C D # 2000-01-01 -0.044333 -0.051989 -1.947218 -0.677572 # 2000-01-02 -0.631469 NaN -1.573849 -0.853425 # 2000-01-03 NaN -0.272759 -0.577754 NaN # 2000-01-04 NaN NaN -0.179180 -0.147158 # 2000-01-05 -0.339024 -0.990385 NaN NaN # 2000-01-06 NaN -0.297956 NaN NaN # 2000-01-07 -0.131227 NaN NaN -1.202555 # 2000-01-08 NaN -1.957476 NaN -0.409341
Кроме того, метод .where()
принимает необязательный аргумент other
для замены значений, если условие cond
имеет значение False
, в возвращаемой копии. Метод .mask()
работает аналогичным образом, только заменяет значения, если условие cond
имеет значение True
>>> df.where(df < 0, -df) # A B C D # 2000-01-01 -0.044333 -0.051989 -1.947218 -0.677572 # 2000-01-02 -0.631469 -2.272832 -1.573849 -0.853425 # 2000-01-03 -0.366391 -0.272759 -0.577754 -0.719210 # 2000-01-04 -1.804667 -0.363212 -0.179180 -0.147158 # 2000-01-05 -0.339024 -0.990385 -0.399724 -0.832043 # 2000-01-06 -0.588127 -0.297956 -1.030587 -0.976066 # 2000-01-07 -0.131227 -0.967801 -0.545073 -1.202555 # 2000-01-08 -0.185359 -1.957476 -1.129694 -0.409341 # эквивалентно >>> df.mask(df > 0, -df) # A B C D # 2000-01-01 -0.044333 -0.051989 -1.947218 -0.677572 # 2000-01-02 -0.631469 -2.272832 -1.573849 -0.853425 # 2000-01-03 -0.366391 -0.272759 -0.577754 -0.719210 # 2000-01-04 -1.804667 -0.363212 -0.179180 -0.147158 # 2000-01-05 -0.339024 -0.990385 -0.399724 -0.832043 # 2000-01-06 -0.588127 -0.297956 -1.030587 -0.976066 # 2000-01-07 -0.131227 -0.967801 -0.545073 -1.202555 # 2000-01-08 -0.185359 -1.957476 -1.129694 -0.409341
Методы .where()
и .mask()
также могут принимать аргументы оси axis
и уровня level
для выравнивания входных данных при выполнении.
>>> df.where(df > 0, df['A'], axis='index') # A B C D # 2000-01-01 -0.044333 -0.044333 -0.044333 -0.044333 # 2000-01-02 -0.631469 2.272832 -0.631469 -0.631469 # 2000-01-03 0.366391 0.366391 0.366391 0.719210 # 2000-01-04 1.804667 0.363212 1.804667 1.804667 # 2000-01-05 -0.339024 -0.339024 0.399724 0.832043 # 2000-01-06 0.588127 0.588127 1.030587 0.976066 # 2000-01-07 -0.131227 0.967801 0.545073 -0.131227 # 2000-01-08 0.185359 0.185359 1.129694 0.185359 # код выше эквивалентен (но быстрее) следующего: >>> df.apply(lambda x, y: x.where(x > 0, y), y=df['A']) # A B C D # 2000-01-01 -0.044333 -0.044333 -0.044333 -0.044333 # 2000-01-02 -0.631469 2.272832 -0.631469 -0.631469 # 2000-01-03 0.366391 0.366391 0.366391 0.719210 # 2000-01-04 1.804667 0.363212 1.804667 1.804667 # 2000-01-05 -0.339024 -0.339024 0.399724 0.832043 # 2000-01-06 0.588127 0.588127 1.030587 0.976066 # 2000-01-07 -0.131227 0.967801 0.545073 -0.131227 # 2000-01-08 0.185359 0.185359 1.129694 0.185359
Методы .where()
и .mask()
могут принимать вызываемый объект в качестве условия cond
и аргумента other
. Функция должна принимать один аргумент (вызывающий Series
или DataFrame
) и возвращать допустимые выходные данные.
>>> tmp = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}) >>> tmp.where(lambda x: x > 4, lambda x: x + 10) # A B C # 0 11 14 7 # 1 12 5 8 # 2 13 6 9
>>> s = pd.Series(range(5)) >>> s.where(s > 0) # 0 NaN # 1 1.0 # 2 2.0 # 3 3.0 # 4 4.0 # dtype: float64 >>> s.mask(s > 0) # 0 0.0 # 1 NaN # 2 NaN # 3 NaN # 4 NaN # dtype: float64
>>> s = pd.Series(range(5)) >>> t = pd.Series([True, False]) >>> s.where(t, 99) # 0 0 # 1 99 # 2 99 # 3 99 # 4 99 # dtype: int64 >>> s.mask(t, 99) # 0 99 # 1 1 # 2 99 # 3 99 # 4 99 # dtype: int64
>>> s.where(s > 1, 10) # 0 10 # 1 10 # 2 2 # 3 3 # 4 4 # dtype: int64 >>> s.mask(s > 1, 10) # 0 0 # 1 1 # 2 10 # 3 10 # 4 10 # dtype: int64
>>> df = pd.DataFrame(np.arange(10).reshape(-1, 2), columns=['A', 'B']) >>> df # A B # 0 0 1 # 1 2 3 # 2 4 5 # 3 6 7 # 4 8 9 >>> m = df % 3 == 0 >>> df.where(m, -df) # A B # 0 0 -1 # 1 -2 3 # 2 -4 -5 # 3 6 -7 # 4 -8 9 >>> df.where(m, -df) == np.where(m, df, -df) # A B # 0 True True # 1 True True # 2 True True # 3 True True # 4 True True >>> df.where(m, -df) == df.mask(~m, -df) # A B # 0 True True # 1 True True # 2 True True # 3 True True # 4 True True