Изменение подмножества строк в фрейме данных pandas
предположим, что у меня есть фрейм данных pandas с двумя столбцами, A и B. Я хотел бы изменить этот фрейм данных (или создать копию), чтобы B всегда был NaN всякий раз, когда A равно 0. Как бы я этого добился?
я попробовал следующее
df['A'==0]['B'] = np.nan
и
df['A'==0]['B'].values.fill(np.nan)
без успеха.
5 ответов:
обновление
ix
устарело, используйте.loc
для индексирования на основе метокdf.loc[df.A==0, 'B'] = np.nan
попробуйте это:
df.ix[df.A==0, 'B'] = np.nan
the
df.A==0
выражение создает логический ряд, который индексирует строки,'B'
выбирает столбец. Вы также можете использовать это для преобразования подмножества столбца, например:df.ix[df.A==0, 'B'] = df.ix[df.A==0, 'B'] / 2
Я не знаю достаточно о внутренностях панд, чтобы точно знать, почему это работает, но основная проблема что иногда индексирование в фрейм данных возвращает копию результата, а иногда возвращает представление исходного объекта. В соответствии с документацией здесь, это поведение зависит от базового поведения numpy. Я обнаружил, что доступ ко всему в одной операции (а не [один][два]), скорее всего, будет работать для настройки.
здесь от Панды документы на дополнительное индексирование:
в разделе будет объяснено, что именно вам нужно! Оказывается
df.loc
(как .ix был устаревшим - как многие указали ниже) может использоваться для холодного нарезания/нарезки кадра данных. И. Он также может быть использован для установки вещей.df.loc[selection criteria, columns I want] = value
поэтому ответ Брена говорит: "Найдите мне все места, где
df.A == 0
выберите столбецB
и установить его вnp.nan
'
начиная с панд 0.20 ix является устаревшим. Правильный способ-использовать
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]
by:
- используя тот факт, что
loc
может возьмите логический массив в качестве маски, которая говорит пандам, какое подмножество строк мы хотим изменить вrow_index
- эксплуатируя факт
loc
также метка на основе, чтобы выбрать столбец с помощью метки'B'
наcolumn_index
мы можем использовать логику, условие или любую операцию, которая возвращает ряд булевых значений для построения массива булевых значений. В приведенном выше примере мы хотим любой
rows
, содержащих0
, для этого мы можем использовать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, где функция.
настройка
создайте Двухколоночный фрейм данных с 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 это
where
это примерно в 4 раза быстрее