2016-09-26 2 views
0

Допустим, у меня есть два массива: и b = array([1,2,3,4,0,5,6]). Я заинтересован в том, чтобы удалить экземпляры, где a и b - 0. Но я также хочу удалить соответствующие экземпляры из обоих списков. Поэтому я хочу, чтобы в итоге было a = array([1,2,3,5]) и b = array([1,2,3,5]). Это связано с тем, что a[3] == 0 и a[6] == 0, поэтому оба b[3] и b[6] также удалены. Кроме того, так как b[4] == 0, a[4] также deleted.Its просто сделать это для скажу два массивов:Удаление значений из нескольких массивов, имеющих определенное значение

import numpy as np 
a = np.array([1,2,3,0,4,5,0]) 
b = np.array([1,2,3,4,0,5,6]) 

ix = np.where(b == 0) 
b = np.delete(b, ix) 
a = np.delete(a, ix) 

ix = np.where(a == 0) 
b = np.delete(b, ix) 
a = np.delete(a, ix) 

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

Если я стараюсь следующее:

import numpy as np 

a = np.array([1,2,3,0,4,5,0]) 
b = np.array([1,2,3,4,0,5,6]) 

arrays = [a,b] 

for array in arrays: 
    ix = np.where(array == 0) 
    b = np.delete(b, ix) 
    a = np.delete(a, ix) 

я a = array([1, 2, 3, 4]) и b = array([1, 2, 3, 0]), а не ответы мне нужно. Любая идея, где это неправильно?

+0

сделать все массивы имеют одинаковую длину? – dnalow

+0

@ dnalow Да, они имеют одинаковую длину. – deserthiker

ответ

1

Это происходит потому, что, когда вы возвращаетесь из np.delete, вы получаете массив, который хранится в b и внутри цикла. Однако массивы, хранящиеся в переменной массива, являются копиями, а не ссылками. Следовательно, когда вы обновляете массивы, удаляя их, они удаляются относительно исходных массивов. Первый цикл вернет правильные индексы 0 в массиве, но второй цикл вернет ix как 4 (посмотрите на исходный массив).
Как если бы вы отображали переменную массива на каждой итерации, она останется прежней.

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

a = np.array([1, 2, 3, 0, 4, 5, 0]) 
b = np.array([1, 2, 3, 4, 0, 5, 6]) 
arrays = [a,b] 
for i in range(0, len(arrays)): 
    ix = np.where(arrays[i] == 0) 
    b = np.delete(b, ix) 
    a = np.delete(a, ix) 
    arrays = [a, b] 

Конечно, вы можете автоматизировать то, что происходит внутри цикла. Я просто хотел дать объяснение происходящему.

+0

Повторное назначение довольно умное, но не упадет ли это в проблему с копией-пастой при масштабировании до более крупных наборов массивов или массивов переменных массивов? –

+0

Я пытаюсь думать о чем-то, что не связано с копированием. Возможно, сделайте несколько массив массивов numpy ... Попробуй и вернись, если мне удастся найти дорогу! – Zeokav

0

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

import numpy as np 

a = np.array([1,2,3,0,4,5,0]) 
b = np.array([1,2,3,4,0,5,6]) 

arrays = [a, b] 
vals = [] 

for array in arrays: 
    ix = np.where(array == 0) 
    vals.extend([y for x in ix for y in x.tolist()]) 

vals = list(set(vals)) 

new_array = [] 
for array in arrays: 
    new_array.append(np.delete(array, vals)) 
+0

Не хотите ли OP, чтобы индексы менялись после каждой итерации? – Zeokav

+0

Говорят, что они хотят удалить из обоих списков элементы по индексам, где хотя бы один из списков содержит 0. И их использование 'b [4] == 0' означает, что они означают, что они не обязательно хотят удалить значения 'a' из' b' сначала перед удалением значений 'b' из' a'. Для меня это говорит: «Составьте список всех индексов, а затем удалите все значения». –

3

Предполагая, что оба/все массивы всегда имеют одинаковую длину, вы можете использовать masks:

ma = a != 0 # mask elements which are not equal to zero in a 
mb = b != 0 # mask elements which are not equal to zero in b 
m = ma * mb # assign the intersection of ma and mb to m 
print a[m], b[m] # [1 2 3 5] [1 2 3 5] 

вы, конечно, можете также сделать это в одной строке

m = (a != 0) * (b != 0) 

Или использовать обратный

ma = a == 0 
mb = b == 0 
m = ~(ma + mb) # not the union of ma and mb 
+0

Не был знаком с масками, @ Кристоф Тераса. Элегантный! – deserthiker

0

Построение на вершине ответа Кристофа TERASA, вы можете использовать операции над массивами, а не для петель:

arrays = np.vstack([a,b]) # ...long list of arrays of equal length 

zeroind = (arrays==0).max(0) 

pos_arrays = arrays[:,~zeroind] # a 2d array only containing those columns where none of the lines contained zeros 
Смежные вопросы