2015-03-18 2 views
3

Если у меня есть Numpy массив, например:дополняют друг друг нарезки в Numpy массива

A = np.array([[3, 2], [2, -1], [2, 3], [5, 6], [7,-1] , [8, 9]]) 

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

Что я делаю на данный момент является:

slicing1 = np.where(A[:, 1] == -1) 
with_ones = A[slicing1] 
slicing2 = np.setdiff1d(np.arange(A.shape[0]), slicing1, assume_unique=True) 
without_ones = A[slicing2] 

Есть ли способ, чтобы не создавать список slicing2, чтобы уменьшить потребление памяти, как это может быть очень большим? Есть ли лучший способ подойти к проблеме?

ответ

6

Один из способов сохранить логический индекс, необходимый, а затем во втором индексе случае с использованием своего логического отрицания:

In [46]: indx = A[:, 1] != -1 

In [47]: A[indx] 
Out[47]: 
array([[3, 2], 
     [2, 3], 
     [5, 6], 
     [8, 9]]) 

In [48]: A[~indx] 
Out[48]: 
array([[ 2, -1], 
     [ 7, -1]]) 
+2

Это, безусловно, лучше, чем использование setdiff1d по многим причинам. И поскольку логические массивы используют только байты для каждого элемента, даже две копии булевского массива индексов будут меньше, чем целочисленный индексный массив и его дополнение. Чтобы сэкономить еще немного памяти, я считаю, что это не сделает копию: 'numpy.logical_not (ix, out = ix)'. – senderle

1

мне удалось создать without_ones с:

filter(lambda x: x[1] != -1,A) 
1

Или вы могли бы использовать функция генератора:

A = np.array([[3, 2], [2, -1], [2, 3], [5, 6], [7,-1] , [8, 9]]) 

def filt(arr): 
    for item in arr: 
     if item[1]!=-1: 
      yield item 

new_len = 0 
for item in A: 
    if item[1] != -1: 
     new_len += 1 

without_ones = np.empty([new_len, 2], dtype=int) 
for i, item in enumerate(filt(A)): 
    without_ones[i] = item 
Смежные вопросы