Выражение np.where(df["If_Seguro"] == 1, np.random.choice(range(1,N_Seg+1),1),0)
показывает, что, на мой взгляд, часто встречается, но обычно нежелательно where
. Решение также ответит на ваш вопрос о том, почему генерируется только одно значение.
np.where
мало вычисляет. Он просто выбирает значения на основе маски из пары существующих массивов. Обычная семантика python здесь не меняется. Вы передаете результат вызова функции, а не саму функцию, поэтому используется значение. Это означает, что вам нужно вычислить np.random.choice(...)
для всех строк df
, а не только для тех, где df["If_Seguro"] == 1
.
df["If_Seguro"]
- маска, а numpy предоставляет вам некоторые инструменты для беспокойства с масками. Например, фактическое количество элементов, которые вы хотите сгенерировать, равно
np.count_nonzero(df["If_Seguro"])
Местоположения строк, в которые вы хотите вставить эти значения, задаются самой маской. И numpy, и pandas позволяют напрямую индексировать с помощью логической маски. np.where
- просто дополнительный уровень неэффективности во многих случаях.
Наконец, чтобы сгенерировать N выборок из существующей последовательности, выполните одно из следующих действий:
np.random.choice(range(1, N_Seg + 1), size=N, replace=True)
replace=True
позволяет выборкам Повторите, поскольку ваш первоначальный вызов np.where
, скорее всего, предназначен. Гораздо лучший способ сделать то же самое - не задействовать явный объект последовательности:
np.random.randint(1, N_Seg + 1, N)
В предлагаемом решении, где будет количество маскируемых элементов, тогда как в исходном коде это должно было быть N
.
Итак, наконец, у нас есть:
mask = df["If_Seguro"]
df.loc[mask, "id_Seguro"] = np.random.randint(1, 1 + N_Seg, np.count_nonzero(mask))
Если id_Seguro
еще не обнулено, вы можете сделать одну из нескольких вещей. Добавление к предыдущему:
df.loc[~mask, "id_Seguro"] = 0
Или создание нового массива с нуля:
mask = df["If_Seguro"]
result = np.zeros(N)
result[mask] = np.random.randint(1, 1 + N_Seg, np.count_nonzero(mask))
df["id_Seguro"] = result