Самый быстрый способ выбрать случайное число из каждого массива numpy с заполнением строк (без заполнения) и количества значений без заполнения, используя операции numpy - PullRequest
2 голосов
/ 26 мая 2020

У меня есть массив 2D numpy, каждая строка дополнена (с -1 для примера ниже).

Для каждой строки я хочу выбрать случайное число, исключая заполнение, а также получить количество незаполненных значений для каждой строки, используя только операции numpy.

Вот минимальный пример. Я выбрал -1 для пэда, но пэд может иметь любое отрицательное значение int.

import numpy as np
numList = [[0, 32, 84, 93, 1023, -1], [0, 23, 33, 45, -1, -1], [0, 10, 15, 21, 24, 25], [0, 23, -1, -1, -1, -1], [0 , 13, 33, 34, -1, -1]]
numArray = np.array(numList)
numArray

array([[   0,   32,   84,   93, 1023,   -1],
       [   0,   23,   33,   45,   -1,   -1],
       [   0,   10,   15,   21,   24,   25],
       [   0,   23,   -1,   -1,   -1,   -1],
       [   0,   13,   33,   34,   -1,   -1]])

Для длин вывод должен выглядеть примерно так:

LengthsResults
[5, 4, 6, 2, 4]. 

А вот пример вывода для выбора случайного числа без заполнителя для каждой строки.

randomNonPad
[84, 45, 0, 0, 34]

Изменить:

Я смотрел np.where, который позволяет фильтровать части вашего массива numpy по условию и numpy случайный выбор, что позволяет вы выбираете случайное число для массива. Я не уверен, что делать с np.where, хотя кажется, что вы можете изменить его на что-то, но я еще не уверен, что, или даже если это правильный подход. Для python вы можете начать со списка и добавлять его любой длины, но для numpy вам нужно заранее установить sh длину массива.

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

Индекс отрицательного числа в строке, который также является длиной элементов без дополнений, проще всего получить с помощью

lengths = np.argmin(numArray, axis=1)

Это предполагает, что номер заполнения одинаков для всех элементов внутри строки. Это не будет работать должным образом для строк без отрицательных чисел, поэтому вы можете исправить это с помощью:

lengths[np.take_along_axis(numArray, lengths.reshape(-1, 1), axis=1).ravel() >= 0] = numArray.shape[1]

Теперь вы можете использовать эту информацию для генерации массива случайных индексов в ваших строках:

indices = np.random.randint(lengths)

И примените индекс, чтобы получить соответствующие элементы:

result = np.take_along_axis(numArray, indices.reshape(-1, 1), axis=1)

Хотя очистка массива lengths, вероятно, будет более быстрым вариантом, более короткое выражение может выглядеть примерно как

lengths = np.where(np.any(numArray < 0, axis=1), np.argmin(numArray, axis=1), numArray.shape[1])

Кроме того, если ваш номер заполнения не является последовательным отрицательным числом, вам нужно будет заменить np.argmin(numArray, axis=1) либо np.argmax(numArray < 0, axis=1), либо np.argmin(numArray >= 0, axis=1), независимо от того, какой подход вы используете для вычисления lengths.

1 голос
/ 26 мая 2020

Примечание - это, вероятно, частично совпадает с ответом @ Mad; Я оставлю это на случай, если альтернативное объяснение устранит некоторую путаницу.

In [32]: numList = [[0, 32, 84, 93, 1023, -1], [0, 23, 33, 45, -1, -1], [0, 10, 15, 21, 2
    ...: 4, 25], [0, 23, -1, -1, -1, -1], [0 , 13, 33, 34, -1, -1]] 
    ...: numArray = np.array(numList)                                                    
In [33]: numArray                                                                        
Out[33]: 
array([[   0,   32,   84,   93, 1023,   -1],
       [   0,   23,   33,   45,   -1,   -1],
       [   0,   10,   15,   21,   24,   25],
       [   0,   23,   -1,   -1,   -1,   -1],
       [   0,   13,   33,   34,   -1,   -1]])

количество контактных площадок в строке:

In [34]: np.sum(numArray==-1, axis=1)                                                    
Out[34]: array([1, 2, 0, 4, 2])

количество не-контактных площадок в строке:

In [35]: np.sum(numArray!=-1, axis=1)                                                    
Out[35]: array([5, 4, 6, 2, 4])

Я не знаю, если предположить, что все значения площадок находятся в конце, делает это более эффективным или нет. Выборка немного мала, чтобы обеспечить хорошее время. (выше) (и предполагая заполнение хвостом) мы могли бы выбрать случайный индекс для каждой строки:

In [46]: [np.random.choice(i) for i in Out[35]]                                          
Out[46]: [1, 2, 1, 0, 1]
In [47]: numArray[np.arange(numArray.shape[0]), [np.random.choice(i) for i in Out[35]]]  
Out[47]: array([93, 45, 21, 23, 13])

В подсказке к @Mad randint принимает список / массив значений диапазона, choice понимание можно заменить на:

In [49]: np.random.randint(Out[35])                                                      
Out[49]: array([3, 1, 2, 1, 1])
In [50]: numArray[np.arange(numArray.shape[0]), np.random.randint(Out[35])]              
Out[50]: array([ 0, 23, 24,  0,  0])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...