2016-07-05 66 views
8

Ho uno m -by- n array numpy e vorrei aggiungere 1.0 a tutte le voci [i, j] quando (i + j) % 2 == 0, cioè "in ogni altro quadrato".Aggiungi valore a ogni campo "altro" ((i + j)% 2 == 0) dell'array numpy

potevo naturalmente semplicemente scorrere i campi

import numpy as np 

a = np.random.rand(5, 4) 

for i in range(a.shape[0]): 
    for j in range(a.shape[1]): 
     if (i + j) % 2 == 0: 
      a[i, j] += 1.0 

ma inutile dire che questo è molto lento.

Qualche idea su come migliorare su questo?

risposta

6

Si può facilmente fare l'operazione in due fasi, come

import numpy as np 

a = np.zeros((5, 14)) 

# Even rows, odd columns 
a[::2, 1::2] += 1 
# Odd rows, even columns 
a[1::2, ::2] += 1 

print a 
5

Ecco un modo utilizzando NumPy broadcasting -

a[(np.arange(a.shape[0])[:,None] + np.arange(a.shape[1]))%2==0] += 1 

Spiegazione: Creiamo fondamentalmente due matrici che sono equivalenti dei i-th e j-th iteratori. Chiamiamoli I e J.

I = np.arange(a.shape[0]) 
J = np.arange(a.shape[1]) 

Ora, per eseguire un'operazione tra tutti i possibili i e j, creiamo estendere I a 2D da spingendo suoi elementi nella primo asse e creando dimensione singoletto lungo il suo secondo asse.

In senso figurato, l'effetto di trasmissione potrebbe essere messo in questo modo:

I[:,None] : M , 1 
      J : 1 , N 
I[:,None] + J : M, N 

Così, l'impostazione finale sarebbe -

a[(I[:,None] + J)%2==0] += 1 

Per dirla altro modo con l'intenzione di evitare il confronto con 0 e utilizzare direttamente mod-2 che sarebbe essenzialmente 0 o 1 -

a += (np.arange(a.shape[0])[:,None]-1 + np.arange(a.shape[1]))%2 

Si può anche utilizzare np.ix_ per elaborare dispari e poi righe anche per l'impostazione, in questo modo -

a[np.ix_(np.arange(0,a.shape[0],2),np.arange(0,a.shape[1],2))] += 1 
a[np.ix_(np.arange(1,a.shape[0],2),np.arange(1,a.shape[1],2))] += 1 
+0

potrebbe si prega di aggiungere qualche spiegazione? Aiuterebbe sicuramente i neofiti a capirlo in un modo migliore. – kmario23

+0

Penso che la soluzione 'np.xi_' dovrebbe avere più enfasi; è circa il doppio più veloce. –

+0

@ NicoSchlömer Beh, la trasmissione mi ha colpito prima, quindi sono arrivato in cima :) – Divakar

1

si può costruire una maschera per "ogni altro" elemento, e applicare l'aggiunta del maschera.

# Create mask 
m00 = np.zeros(a.shape[0], dtype=bool) 
m00[0::2] = True 
m01 = np.zeros(a.shape[1], dtype=bool) 
m01[0::2] = True 
m0 = np.logical_and.outer(m00, m01) 

m10 = np.zeros(a.shape[0], dtype=bool) 
m10[1::2] = True 
m11 = np.zeros(a.shape[1], dtype=bool) 
m11[1::2] = True 
m1 = np.logical_and.outer(m10, m11) 

m = np.logical_or(m0, m1) 
a[m] += 1