2014-10-20 2 views
1

Я хочу разбить массив numpy на три разных массива на основе логического сравнения. Массив numpy, который я хочу разбить, называется x. Это форма выглядит следующим образом, но это элементы различны: (В ответ на комментарий Saullo Кастро я включил несколько иной массив х.)Эффективно выберите подраздел numpy array

array([[ 0.46006547, 0.5580928 , 0.70164242, 0.84519205, 1.4  ], 
     [ 0.00912908, 0.00912908, 0.05  , 0.05  , 0.05  ]]) 

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

array([ 0.633, 0.01 ]), array([ 1.325, 0.99 ]) 

Процедура выбора Я хочу подать заявление выглядит следующим образом:

  • Все столбцы, содержащие значения ниже, чем любое значение в lowest_gridpoints следует удалить из x и составить массив temp1.
  • Все столбцы, содержащие значения, превышающие любое значение в highest_gridpoints, должны быть удалены с x и составляют массив temp2.
  • Все столбцы x, которые не включены ни в temp1, ни temp2 составляют массив x_new.

Следующий код, который я написал, выполняет задачу.

if np.any(x[:,-1] > highest_gridpoints) or np.any(x[:,0] < lowest_gridpoints): 
    for idx, sample, in enumerate(x.T): 
     if np.any(sample > highest_gridpoints): 
      max_idx = idx 
      break 
     elif np.any(sample < lowest_gridpoints): 
      min_idx = idx 
    temp1, temp2 = np.array([[],[]]), np.array([[],[]]) 
    if 'min_idx' in locals(): 
     temp1 = x[:,0:min_idx+1] 
    if 'max_idx' in locals(): 
     temp2 = x[:,max_idx:] 
    if 'min_idx' in locals() or 'max_idx' in locals(): 
     if 'min_idx' not in locals(): 
      min_idx = -1 
     if 'max_idx' not in locals(): 
      max_idx = x.shape[1] 
     x_new = x[:,min_idx+1:max_idx] 

Однако, я подозреваю, что этот код очень неэффективен из-за интенсивного использования петель. Кроме того, я думаю, что синтаксис раздувается.

Есть ли у кого-то идеи для кода, который более эффективно выполняет задачу, описанную выше, или выглядит лаконично?

+0

ваш пример возвращает '[]' для меня ... было бы неплохо иметь другой вход, который может быть использован для сравнения ... –

+1

@SaulloCastro: Спасибо вы за свой комментарий. Я слегка изменил массив x. У вас есть идея о том, как изменить код? – fabian

+1

Вы ожидаете, что temp1 и temp2 будут взаимоисключающими, или может случиться, что столбец имеет как значение, меньшее, чем значение в «lower_gridpoints», и другое значение, превышающее значение в «high_gridpoints»? Кроме того, вы имели в виду монотонное увеличение по рядам? – greschd

ответ

1

Только первая часть вашего вопроса

from numpy import * 

x = array([[ 0.46006547, 0.5580928 , 0.70164242, 0.84519205, 1.4  ], 
      [ 0.00912908, 0.00912908, 0.05  , 0.05  , 0.05  ]]) 

low, high = array([ 0.633, 0.01 ]), array([ 1.325, 0.99 ]) 

# construct an array of two rows of bools expressing your conditions 
indices1 = array((x[0,:]<low[0], x[1,:]<low[1])) 
print indices1 

# do an or of the values along the first axis 
indices1 = any(indices1, axis=0) 
# now it's a single row array 
print indices1 

# use the indices1 to extract what you want, 
# the double transposition because the elements 
# of a 2d array are the rows 
tmp1 = x.T[indices1].T 
print tmp1 

# [[ True True False False False] 
# [ True True False False False]] 
# [ True True False False False] 
# [[ 0.46006547 0.5580928 ] 
# [ 0.00912908 0.00912908]] 

рядом строится аналогично indices2 и tmp2, показатели остатка являются отрицанием or Инг первых двух индексов. (то есть numpy.logical_not(numpy.logical_or(i1,i2))).

Добавление

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

from numpy import * 

x = array([[ 0.46006547, 0.5580928 , 0.70164242, 0.84519205, 1.4  ], 
      [ 0.00912908, 0.00912908, 0.05  , 0.05  , 0.05  ]]) 

low, high = array([ 0.633, 0.01 ]), array([ 1.325, 0.99 ]) 

l0r = searchsorted(x[0,:], low[0], side='right') 
l1r = searchsorted(x[1,:], low[1], side='right') 

h0l = searchsorted(x[0,:], high[0], side='left') 
h1l = searchsorted(x[1,:], high[1], side='left') 

lr = max(l0r, l1r) 
hl = min(h0l, h1l) 

print lr, hl 
print x[:,:lr] 
print x[:,lr:hl] 
print x[:,hl] 

# 2 4 
# [[ 0.46006547 0.5580928 ] 
# [ 0.00912908 0.00912908]] 
# [[ 0.70164242 0.84519205] 
# [ 0.05  0.05  ]] 
# [ 1.4 0.05] 

исключающие дублирование может быть получено hl = max(lr, hl). NB в previuos подходят к массивам массивов, копируются в новые объекты, здесь вы получаете представления на x, и вы должны быть явными, если хотите новые объекты.

Редактироватьненужная оптимизация

Если мы будем использовать только верхнюю часть x во второй паре sortedsearch эс (если вы посмотрите на код, вы увидите, что я имею в виду ...) мы получаем два преимущества: 1) очень небольшое ускорение поиска (sortedsearch всегда достаточно быстро) и 2) случай перекрытия автоматически управляется.

В качестве бонуса, код для копирования сегментов x в новые массивы. NB x была изменена, чтобы заставить перекрываться

from numpy import * 

# I changed x to force overlap 
x = array([[ 0.46006547, 1.4 ,  1.4, 1.4, 1.4  ], 
      [ 0.00912908, 0.00912908, 0.05, 0.05, 0.05  ]]) 

low, high = array([ 0.633, 0.01 ]), array([ 1.325, 0.99 ]) 

l0r = searchsorted(x[0,:], low[0], side='right') 
l1r = searchsorted(x[1,:], low[1], side='right') 
lr = max(l0r, l1r) 

h0l = searchsorted(x[0,lr:], high[0], side='left') 
h1l = searchsorted(x[1,lr:], high[1], side='left') 

hl = min(h0l, h1l) + lr 

t1 = x[:,range(lr)] 
xn = x[:,range(lr,hl)] 
ncol = shape(x)[1] 
t2 = x[:,range(hl,ncol)] 

print x 
del(x) 
print 
print t1 
print 
# note that xn is a void array 
print xn 
print 
print t2 

# [[ 0.46006547 1.4   1.4   1.4   1.4  ] 
# [ 0.00912908 0.00912908 0.05  0.05  0.05  ]] 
# 
# [[ 0.46006547 1.4  ] 
# [ 0.00912908 0.00912908]] 
# 
# [] 
# 
# [[ 1.4 1.4 1.4 ] 
# [ 0.05 0.05 0.05]] 
+0

Я начинаю опасаться, что я не понял требования OP. – gboffi

+0

Спасибо за ваш ответ; ваше приложение отлично работало для меня, за исключением одной модификации: Чтобы избежать дублирования, мне пришлось использовать '' if hl fabian