Предположим, у меня есть DataFrame pandas с двумя столбцами, A и B. Я хотел бы изменить этот DataFrame (или создать копию), чтобы B всегда был NaN, когда A равно 0. Как мне этого добиться?
Я пробовал следующее
df['A'==0]['B'] = np.nan
а также
df['A'==0]['B'].values.fill(np.nan)
безуспешно.
where
как показано в этом решении нижеОтветы:
Используйте
.loc
для индексации на основе меток:df.loc[df.A==0, 'B'] = np.nan
df.A==0
Выражение создает булев ряд , что индексы строк,'B'
выбирает столбец. Вы также можете использовать это для преобразования подмножества столбца, например:df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2
Я недостаточно знаю о внутреннем устройстве pandas, чтобы точно знать, почему это работает, но основная проблема заключается в том, что иногда индексация в DataFrame возвращает копию результата, а иногда возвращает представление исходного объекта. Согласно документации здесь , это поведение зависит от основного поведения numpy. Я обнаружил, что доступ ко всему за одну операцию (а не [один] [два]) с большей вероятностью будет работать для настройки.
источник
Вот из документов pandas о расширенном индексировании:
Раздел объяснит, что именно вам нужно! Оказывается
df.loc
(поскольку .ix устарел - как многие указывали ниже) можно использовать для классной нарезки / нарезки фрейма данных. А также. Его также можно использовать для настройки вещей.Итак, ответ Брена гласит: «Найди мне все места, где
df.A == 0
, выберите столбецB
и установите егоnp.nan
»источник
loc[selection criteria, columns I want]
отличноНачиная с pandas 0.20 ix устарела . Правильный способ - использовать df.loc
вот рабочий пример
>>> import pandas as pd >>> import numpy as np >>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB')) >>> df.loc[df.A == 0, 'B'] = np.nan >>> df A B 0 0 NaN 1 1 0 2 0 NaN >>>
Пояснение:
Как объясняется здесь ,
.loc
в основном это метка, но может также использоваться с логическим массивом .Итак, то, что мы делаем выше, применяется
df.loc[row_index, column_index]
:loc
логический массив может использоваться в качестве маски, которая сообщает пандам, какое подмножество строк мы хотим изменитьrow_index
loc
также основано на метке для выбора столбца с помощью метки'B'
вcolumn_index
Мы можем использовать логические, условные или любую операцию, возвращающую серию логических значений, для создания массива логических значений. В приведенном выше примере нам нужны все,
rows
которые содержат a0
, для этого мы можем использоватьdf.A == 0
, как вы можете видеть в приведенном ниже примере, это возвращает серию логических значений.>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB')) >>> df A B 0 0 2 1 1 0 2 0 5 >>> df.A == 0 0 True 1 False 2 True Name: A, dtype: bool >>>
Затем мы используем указанный выше массив логических значений для выбора и изменения необходимых строк:
>>> df.loc[df.A == 0, 'B'] = np.nan >>> df A B 0 0 NaN 1 1 0 2 0 NaN
Дополнительные сведения см. В документации по расширенному индексированию здесь .
источник
Для значительного увеличения скорости используйте функцию NumPy where.
Настроить
Создайте двухколоночный DataFrame со 100 000 строками с некоторыми нулями.
df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))
Быстрое решение с
numpy.where
df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
Сроки
%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values) 685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit df.loc[df['a'] == 0, 'b'] = np.nan 3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Numpy's
where
примерно в 4 раза быстрееисточник
.values
вnp.where(df.a.values == 0, np.nan, df.b.values)
? Похоже,np.where(df.a == 0, np.nan, df.b)
тоже работает?Чтобы заменить кратные столбцы, конвертируйте в массив numpy, используя
.values
:df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
источник