np.where () вычисляет np.random.choice () только один раз - pandas - PullRequest
1 голос
/ 16 марта 2020

У меня есть этот фрейм данных:

np.random.seed(0)
N = 10000
N_Seg = 100
df = pd.DataFrame({"Rut_Num": range(1,N+1),
              "Segmento": np.random.choice(
                      ["Afluente", "Afluente","Premium", "Preferente", "Preferente", "Preferente", "Preferente", "Clásico", "Clásico", "Clásico", "Clásico", "Clásico", "Clásico"], N),
              "If_Seguro": np.random.choice([0,1,1], N)})
df.head()

   Rut_Num    Segmento  If_Seguro
0        1     Clásico          1
1        2  Preferente          0
2        3    Afluente          0
3        4  Preferente          0
4        5     Clásico          1

Когда столбец If_Seguro равен 1, мне нужно случайное число от 1 до N_Seg+1, если его 0, мне нужно 0:

np.random.seed()
df.loc[:,"id_Seguro"] = np.where(df["If_Seguro"] == 1, np.random.choice(range(1,N_Seg+1),1),0)
df["id_Seguro"].value_counts()

Вы можете видеть, что истинное условие np.where() даст одинаковое число для всех, когда мне нужно случайное число для каждого 1 из If_Seguro

Кроме того, почему np.where() вычисляет np.random.choice() только один раз для всего столбца и не вычисляет его для каждой проверки (каждой строки) в столбце?

1 Ответ

2 голосов
/ 16 марта 2020

Выражение 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...