2015-08-07 3 views
1

У меня есть 3d Numpy массив следующим образом:NumPy массива Индексирование и замена

(3L, 5L, 5L) 

Если один элемент в 3d позиции, например, [150, 160, 170] существует. Как я могу преобразовать их все в [0,0,0]?

import numpy as np 
a = np.ones((3,5,5)) 
a[0,2:4,2:4] = 150 
a[0,0:1,0:1] = 150 #important! 
a[1,2:4,2:4] = 160 
a[2,2:4,2:4] = 170 
print a 

Ожидаемый результат должен быть:

[[[ 1. 1. 1. 1. 1.] 
    [ 1. 1. 1. 1. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 1. 1. 1.]] 

[[ 1. 1. 1. 1. 1.] 
    [ 1. 1. 1. 1. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 1. 1. 1.]] 

[[ 1. 1. 1. 1. 1.] 
    [ 1. 1. 1. 1. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 0. 0. 1.] 
    [ 1. 1. 1. 1. 1.]]] 
+0

np.where (условие) –

+0

try np.where (a> 1) –

+0

Вопрос и пример должны сделать более понятным, что '[150,160,170]' должны произойти вместе. – hpaulj

ответ

2

Сначала я бы преобразовать в стек троек:

b = np.reshape(a.transpose(2, 1, 0), [25,3]) 

Затем найдите нужные значения:

idx = np.where((b == np.array([150, 160, 170])).all(axis=1)) 

И замените все, что вам нужно хочу:

b[idx] = 0 

И, наконец, преобразовать обратно в исходную форму:

c = np.reshape(b, [5, 5, 3]).transpose(2, 1, 0) 
2

Построить свой a:

In [48]: a=np.ones((3,5,5))  
In [49]: a[0,2:4,2:4]=150 
In [50]: a[1,2:4,2:4]=160 
In [51]: a[2,2:4,2:4]=170 

In [52]: a 
Out[52]: 
array([[[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 150., 150., 1.], 
     [ 1., 1., 150., 150., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 160., 160., 1.], 
     [ 1., 1., 160., 160., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 170., 170., 1.], 
     [ 1., 1., 170., 170., 1.], 
     [ 1., 1., 1., 1., 1.]]]) 

Boolean из всех мест, где значения, на 1-ом измерении, являются [150,160,170]. Ключ должен расширить это до 3D, формы (3,1,1), которые могут транслироваться на (3,5,5) и по сравнению с a:

In [53]: I = a==np.array([150,160,170])[:,None,None] 

In [54]: I 
Out[54]: 
array([[[False, False, False, False, False], 
     [False, False, False, False, False], 
     [False, False, True, True, False], 
     [False, False, True, True, False], 
     [False, False, False, False, False]], 

     [[False, False, False, False, False], 
     [False, False, False, False, False], 
     [False, False, True, True, False], 
     [False, False, True, True, False], 
     [False, False, False, False, False]], 

     [[False, False, False, False, False], 
     [False, False, False, False, False], 
     [False, False, True, True, False], 
     [False, False, True, True, False], 
     [False, False, False, False, False]]], dtype=bool) 

Теперь это тривиально, чтобы изменить все эти слоты со значением True в 0:

In [55]: a[I]=0 

In [56]: a 
Out[56]: 
array([[[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 0., 0., 1.], 
     [ 1., 1., 1., 1., 1.]]]) 

Глядя на комментарии к удаленному ответу, я вижу, что вам действительно нужен случай, когда все 3 значения совпадают. То есть, вопреки вашему примеру, могут быть другие слоты a[0,...] - 150 и т. Д., Которые вы не хотите изменять.

Вы могли бы еще работать с этим I, просто принимая в all на 1-ой оси:

In [58]: a[:,I.all(axis=0)]=2 

In [59]: a 
Out[59]: 
array([[[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 1., 1., 1.]], 

     [[ 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 2., 2., 1.], 
     [ 1., 1., 1., 1., 1.]]]) 

Концептуально мой ответ не отличается от принятого одного. Это преобразует массив в 2d, поэтому сопоставление может быть выполнено с помощью 1d [150,160,170]. Фактически он автоматически преобразуется в (1,3), который может быть передан снова в (25,3). Транспонирование и перестройка - это удобный способ стандартизации формата таких проблем, хотя это часто не требуется.


Это может помочь разделить это последнее действие вверх:

In [60]: J=I.all(axis=0) 

In [61]: J 
Out[61]: 
array([[False, False, False, False, False], 
     [False, False, False, False, False], 
     [False, False, True, True, False], 
     [False, False, True, True, False], 
     [False, False, False, False, False]], dtype=bool) 

In [62]: a[:, J] = 3 

или использовать np.where для преобразования булева массива в 2 списка индексов:

In [73]: jj=np.where(J) 
In [74]: jj 
Out[74]: (array([2, 2, 3, 3], dtype=int32), array([2, 3, 2, 3], dtype=int32)) 

In [75]: a[:, jj[0], jj[1]] = 4 

a[:,jj] не работает , но a[(slice(None),)+jj] ... Это последнее выражение создает трехэлементный кортеж, эквивалентный [75].

Я мог бы также расширить J до размера и формы, что соответствует a:

In [90]: K=J[None,...].repeat(3,0) 
In [91]: K 
Out[91]: 
array([[[False, False, False, False, False], 
     [False, False, False, False, False], 
     [False, False, True, True, False], 
     [False, False, True, True, False], 
     [False, False, False, False, False]], 

     [[False, False, False, False, False], 
     ....]], dtype=bool) 

и использовать a[K].

+0

После того как 'a [:, I.all (axis = 0)] = 2' часть немного сложна. Не удается ли получить индексы с помощью 'I = a == np.array ([150,160,170]) [:, None, None]' и определить некоторую ось, подобную (1,3)? – Borys

+0

Я подробно остановился на индексировании «I.all». – hpaulj

Смежные вопросы