Формирование массива numpy 2D на основе другого массива 1D

#python #arrays #numpy #numpy-ndarray

#python #массивы #numpy #numpy-ndarray

Вопрос:

У меня есть (n,m) массив arr1 , где n почти 2,5 миллиона и m =100 . Другой arr2 есть (n, 1) .
Я хочу изменить arr1 таким образом, чтобы:

 arr1[i, j] = arr1[i, j], if j <= arr2[i]
           = nan       , otherwise
  

Пример arr1 и arr2 следующие (обратите внимание, что arr1 также может быть float, arr2 всегда int):

 import numpy as np
arr1 = np.random.randint(500, size=(4,3))
arr1
    array([[147,  46, 168],
           [232, 446, 415],
           [ 21, 245, 214],
           [246, 194, 271]])
arr2 = np.random.randint(4, size=(4,))
arr2
    array([3, 0, 2, 1])
  

Желаемый результат в этом случае был бы:

 array([[147,  46, 168],
       [nan, nan, nan],
       [ 21, 245, nan],
       [246, nan, nan]])
  

Реалистичный образец для проверки скорости — это

 import numpy as np
arr1 = np.random.randint(500, size=(2500000, 100))
arr2 = np.random.randint(101, size=(2500000,))
  

Комментарии:

1. Так arr2 является массивом целых чисел?

2. @WillemVanOnsem да, но arr1 также может быть float.

3. не должен ли случайный диапазон для arr2 быть 100 вместо 100? В противном случае мы получили бы ошибку вне диапазона, верно?

4. @RolandDeschain Я предполагаю, что индекс начинается с 1, а не с 0. Но если исходить из 0, то да, 100 вместо 101

5. @Gerry Python индексируется на основе 0. Итак, вы хотите 100 вместо 101

Ответ №1:

В вашем примере: arr2[:,None] <= list(range(3)) предоставит вам логический массив, указывающий список элементов, которые необходимо заменить на nan.

Итак

 mask = arr2[:,None] <= list(range(arr1.shape[1]))
result = arr1.astype(float)
result[mask] = np.nan