Вместо зацикливания вы можете использовать df.update()
вот так, чтобы получить ускорение> 20x:
df = pd.DataFrame(np.random.choice([0, 0.05], size=(4000, 1000)))
%timeit df.update(np.random.choice([0, 0.05], size=df.shape), filter_func=lambda x: x==0.05)
#498 ms ± 19.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
df = pd.DataFrame(np.random.choice([0, 0.05], size=(4000, 1000)))
%timeit df.applymap(lambda x: np.random.choice([0, 0.05]) if x == 0.05 else 0)
#9.66 s ± 634 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Я заметил, что ускорение увеличивается только длябольшие и большие кадры данных, но уже здесь applymap заняло так много времени, что я решил не увеличивать размер DataFrame дальше.
Как это работает
df = pd.DataFrame(np.random.choice([0, 0.05], size=(1000, 1000)))
print(df.tail(2))
df.update(np.random.choice([0, 0.05], size=df.shape), filter_func=lambda x: x==0.05)
print(df.tail(2))
# 0 1 2 3 4 5 ... 994 995 996 997 998 999
#998 0.00 0.05 0.05 0.0 0.05 0.05 ... 0.0 0.05 0.05 0.05 0.05 0.0
#999 0.05 0.00 0.05 0.0 0.05 0.05 ... 0.0 0.05 0.05 0.05 0.00 0.0
#
#[2 rows x 1000 columns]
# 0 1 2 3 4 5 ... 994 995 996 997 998 999
#998 0.00 0.05 0.00 0.0 0.05 0.05 ... 0.0 0.05 0.05 0.0 0.05 0.0
#999 0.05 0.00 0.05 0.0 0.05 0.00 ... 0.0 0.00 0.05 0.0 0.00 0.0
#
#[2 rows x 1000 columns]
С update
вы можетеизменить выбранные значения из DataFrame.Чтобы выбрать значения (по умолчанию np.nan
), используйте filter_func= lambda x: x==0.05
, а затем создайте DataFrame того же размера, что и исходный DataFrame, со случайным выбором из [0, 0.05]
.Затем он выбирает значения из исходного DataFrame, где значение было 0.05
, и заменяет его случайным значением.