Я нашел две формы замены некоторых значений фрейма данных на основе условия:
mask = df['param'].isnull()
df.loc[mask, 'param'] = 'new_value'
mask = df['param'].isnull()
df['param'] = np.where(mask, 'new_value', df['param'])
Обе формы работают хорошо, но какая предпочтительнее? И в связи с вопросом, когда я должен использовать .loc и когда нп.где?
Спасибо. Мне было интересно, есть ли ответ, основанный не на вкусах или мнениях, а на реальных причинах, но это нормально.
Ну, не полный тест, но вот образец. В каждом прогоне (loc
, np.where
) данные сбрасываются до исходного случайного с начальным числом.
Здесь больше np.nan
, чем допустимых значений. Кроме того, столбец имеет плавающий тип.
np.random.seed(1)
df = pd.DataFrame({'param': np.random.choice((1, np.nan), 1000000, p=(0.3,0.7))})
# loc
%%timeit
mask = df['param'].isnull()
df.loc[mask, 'param'] = 'new_value'
# 46.7 ms ± 177 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# np.where
%%timeit
mask = df['param'].isnull()
df['param'] = np.where(mask, 'new_value', df['param'])
# 86.8 ms ± 2.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Здесь np.nan
меньше допустимых значений, а столбец объектного типа:
np.random.seed(1)
df = pd.DataFrame({'param': np.random.choice(("1", np.nan), 1000000, p=(0.7,0.3))})
та же история:
df.loc[mask, 'param'] = 'new_value'
# 47.8 ms ± 350 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
df['param'] = np.where(mask, 'new_value', df['param'])
# 58.9 ms ± 1.72 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Таким образом, вопреки комментарию @cs95, loc
, кажется, превосходит np.where
.
Спасибо! Да, определенно эти результаты противоречат тому, что указал @cs95.
Обычно это не имеет значения, но
np.where
обычно быстрее, потому что работа с NumPy напрямую позволяет избежать некоторых накладных расходов панд. OTOH, использованиеloc
считается пандическим способом ведения дел. Но это только мое мнение, и этот вопрос основан на мнении, поэтому я голосую за закрытие.