Самый быстрый способ проверить, какие строки в матрице Numpy соответствуют условиям значений?

#python #python-3.x #performance #numpy

Вопрос:

У меня есть 2D numpy array . Каждая строка содержит данные с временной выборкой, которые должны соответствовать нескольким различным возможным критериям.

Для каждой строки необходимо применять несколько различных критериев. Каждая строка-это данные из системы, и каждый критерий представляет собой различную ситуацию, которую можно обнаружить. Условие критериев определяется, если выбранные столбцы в строке находятся в определенном интервале (больше и меньше определенных значений).

Есть ли способ сделать это очень быстро и эффективно numpy ? Я осматривался и на самом деле не нашел способа, хотя я новичок в numpy этом .

Я думал о механизме хэширования, таком как хранение некоторого хэша для каждой строки и проверка соответствия хэша критериев хэшу этой строки. Однако механизм хэширования будет работать только с фиксированными значениями, а не с диапазонами значений. Поэтому это было бы на самом деле неприменимо.

Примеры данных:

 import numpy as np
myData = np.array([[7.241, 7.123, 9.0, 1.2, 1.0, 1.5, 67.14, 162.32], [8.123, 10.4, 7.68, 1.6,0.7, 2.3, 21.2, 175.2]])
 

Примерные условия:

 Criteria #1: 
   condition 1 : column 1 must be greater than 6 and less than 7
   condition 2 : column 4 must be greater than 0 and less than 2
   condition 3 : column 6 must be greater than 10 and less than 50
   (conditions are 'and' operation, so all conditions must be met for criteria to be met or not)
Criteria #2: 
   condition 1 : column 3 must be greater than 10 and less than 22
   condition 2 : column 4 must be greater than 9 and less than 15 
 

Я думал о том numpy , поддерживает ли, так сказать, какое-то регулярное выражение в этом отношении. Существуют ли какие-либо механизмы или методы, numpy которые могли бы эффективно способствовать этому?

Приведенный выше пример прост, но в реальном применении матрица будет содержать несколько сотен строк, и для каждой строки может быть несколько десятков критериев для оценки.

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

1. (myData[:,0}>6)amp;(myData[:,0]<7) создает 1d логический массив, по одному элементу в строке (все ложно!). Аналогично для других тестов столбцов.

2. Несколько сотен строк-это крошечное число на любой современной машине.

Ответ №1:

Первый вариант: простое векторизованное сравнение:

 c1 = (data[:, 0] > 6) amp; (data[:, 0] < 7) amp; (data[:, 3] > 0) amp; (data[:, 3] < 2) amp; (data[:, 5] > 10) amp; (data[:, 5] < 50)
 

c1 является логической маской местоположений, в которых строка запускает критерий 1. Вы можете использовать его в качестве индекса в первом измерении data .

Второй вариант: извлеките интересующие столбцы и сравните их с верхним и нижним критериями одновременно:

 c1lower = [6, 0, 10]
c1upper = [7, 2, 50]
c1cols = data[:, [0, 3, 5]] # this is a copy
c1 = ((c1cols > c1lower) amp; (c1cols < c1upper)).all(1)
 

Копирование данных может быть медленнее, но объединение их по всей строке должно быть быстрее.

В обоих случаях вы можете преобразовать логическую маску в числовой индекс с помощью np.where , np.nonzero , np.flatnonzero или np.argwhere .