Условное замещение Pandas
Я, наверное, делаю что-то очень глупое, но я в тупике.
У меня есть датафрейм, и я хочу заменить значения в определенном столбце, которые превышают значение на ноль. Я думал, что это был способ достижения этого:
df[df.my_channel > 20000].my_channel = 0
Если я скопирую канал в новый фрейм данных, это будет просто:
df2 = df.my_channel
df2[df2 > 20000] = 0
это именно то, что я хочу, но, похоже, не работает с каналом как частью исходного кадра данных.
Ответы
Ответ 1
.ix
индексатор работает нормально для версий панд до 0.20.0, но, поскольку pandas 0.20.0, индексатор .ix
устарел, поэтому вам следует избегать его использования. Вместо этого вы можете использовать индексаторы .loc
или iloc
. Вы можете решить эту проблему:
mask = df.my_channel > 20000
column_name = 'my_channel'
df.loc[mask, column_name] = 0
Или в одну строку
df.loc[df.my_channel > 20000, 'my_channel'] = 0
mask
помогает вам выбрать строки, в которых df.my_channel > 20000
имеет значение True
, а df.loc[mask, column_name] = 0
устанавливает значение 0 для выбранных строк, где mask
содержится в столбце, имя которого равно column_name
.
Обновление: в этом случае вы должны использовать loc
потому что если вы используете iloc
, вы получите NotImplementedError
сообщающую, что логическое индексирование на основе iLocation для целочисленного типа недоступно.
Ответ 2
Пытаться
df.loc[df.my_channel > 20000, 'my_channel'] = 0
Примечание. Начиная с версии 0.20.0, ix
устарела в пользу loc
/iloc
.
Ответ 3
Функция np.where
работает следующим образом:
df['X'] = np.where(df['Y']>=50, 'yes', 'no')
В вашем случае вы хотели бы:
import numpy as np
df['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)
Ответ 4
Причина, по которой исходный фрейм данных не обновляется, заключается в том, что цепная индексация может привести к изменению копии, а не к просмотру вашего фрейма данных. Документы дают этот совет:
При установке значений в объекте pandas необходимо соблюдать осторожность, чтобы избежать так называемой цепной индексации.
У вас есть несколько альтернатив: -
loc
+ логическое индексирование
loc
может использоваться для установки значений и поддерживает логические маски:
df.loc[df['my_channel'] > 20000, 'my_channel'] = 0
mask
+ логическое индексирование
Вы можете назначить для вашей серии:
df['my_channel'] = df['my_channel'].mask(df['my_channel'] > 20000, 0)
Или вы можете обновить свою серию на месте:
df['my_channel'].mask(df['my_channel'] > 20000, 0, inplace=True)
np.where
+ логическое индексирование
Вы можете использовать NumPy, назначив свою оригинальную серию, когда ваше условие не выполнено; однако первые два решения более чистые, поскольку они явно изменяют только указанные значения.
df['my_channel'] = np.where(df['my_channel'] > 20000, 0, df['my_channel'])
Ответ 5
Попробуй это:
df.my_channel = df.my_channel.where(df.my_channel <= 20000, other= 0)
или же
df.my_channel = df.my_channel.mask(df.my_channel > 20000, other= 0)
Ответ 6
Я бы использовал lambda
функцию в Series
DataFrame
следующим образом:
f = lambda x: 0 if x>100 else 1
df['my_column'] = df['my_column'].map(f)
Я не утверждаю, что это эффективный способ, но он прекрасно работает.