Выбор строк в массиве NumPy - PullRequest
       1

Выбор строк в массиве NumPy

0 голосов
/ 15 сентября 2018

У меня есть массив NumPy (mat) формы (n,4).Массив имеет четыре столбца и большое количество (n) строк.Первые три столбца представляют x, y, z столбцы в моем расчете.Я хочу выбрать те строки массива numpy, где столбец x имеет значения ниже заданного числа (min_x) или значения выше указанного числа (max_x), а столбец y имеет значения нижезаданное число (min_y) или значения выше заданного числа (max_y) и где столбец z имеет значения ниже заданного числа (min_z) или значения выше заданного числа (max_z).

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

import numpy as np

mark = np.where( ( (mat[:,0]<=min_x) | \
            (mat[:,0]>max_x) ) & \
                 ( (mat[:,1]<=min_y) | \
            (mat[:,1]>max_y) ) & \
                 ( (mat[:,2]<=min_z) | \
            (mat[:,2]>max_z) ) )

mat_new = mat[:,mark[0]]

Является ли метод, который я использую, правильным и наилучшим способом достижения желаемой функциональности?Я буду очень признателен за любую помощь.Спасибо.

Ответы [ 3 ]

0 голосов
/ 15 сентября 2018

Я бы просто сбросил np.where и использовал бы вместо этого логическую маску

x,y,z,_ = mat.T
mask = ( ( (x <= min_x) | (x > max_x) ) &
         ( (y <= min_y) | (y > max_y) ) &
         ( (z <= min_z) | (z > max_z) ) ) 
mat_new = mat[mask]
0 голосов
/ 15 сентября 2018

То, что у вас сейчас выглядит отлично. Но поскольку вы спрашиваете о других способах достижения желаемой функциональности: вы можете создать одномерную логическую маску, равную True или False для каждого индекса строки. Вот пример.

>>> import numpy as np
>>> np.random.seed(444)

>>> shape = 15, 4
>>> mat = np.random.randint(low=0, high=10, size=shape)
>>> mat
array([[3, 0, 7, 8],
       [3, 4, 7, 6],
       [8, 9, 2, 2],
       [2, 0, 3, 8],
       [0, 6, 6, 0],
       [3, 0, 6, 7],
       [9, 3, 8, 7],
       [3, 2, 6, 9],
       [2, 9, 8, 9],
       [3, 2, 2, 8],
       [1, 5, 6, 7],
       [6, 0, 0, 0],
       [0, 4, 8, 1],
       [9, 8, 5, 8],
       [9, 4, 6, 6]])

# The thresholds for x, y, z, respectively
>>> lower = np.array([5, 5, 4])
>>> upper = np.array([6, 6, 7])
>>> idx = len(lower)
# Parentheses are required here.  NumPy boolean ops use | and &
# which have different operator precedence than `or` and `and`
>>> mask = np.all((mat[:, :idx] < lower) | (mat[:, :idx] > upper), axis=1)

>>> mask
array([False, False,  True,  True, False, False,  True, False,  True,
        True, False, False,  True, False, False])

Теперь индексирование mat по mask ограничит его индексами строк, где mask равно True:

>>> mat[mask]
array([[8, 9, 2, 2],
       [2, 0, 3, 8],
       [9, 3, 8, 7],
       [2, 9, 8, 9],
       [3, 2, 2, 8],
       [0, 4, 8, 1]])

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

np.all() говорит, проверяет, что все значения True, по строкам. Он фиксирует условия "и" из вашего вопроса, в то время как оператор | фиксирует "или".

0 голосов
/ 15 сентября 2018

выглядит хорошо для меня. Вы можете сделать его немного более компактным, сравнив столбцы со средними значениями:

mark = (np.abs(mat[:,0] - (max_x + min_x) / 2) > (max_x - min_x) / 2) &
       (np.abs(mat[:,1] - (max_y + min_y) / 2) > (max_y - min_y) / 2) &
       (np.abs(mat[:,2] - (max_z + min_z) / 2) > (max_z - min_z) / 2)

К сожалению, вы больше не можете контролировать точные граничные условия (< против <=). Кроме того, это, вероятно, самое медленное решение, даже медленнее, чем оригинальное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...