2012-05-21 4 views
8

Si tengo una matriz de esta manera:Reducir la resolución de la matriz a través de la suma

a = np.array([[ 1, 2, 3, 4], 
       [ 5 ,6, 7, 8], 
       [ 9,10,11,12], 
       [13,14,15,16]]) 

quiero 'cambiar la resolución', y terminan con una gama más pequeña, (digamos 2 filas por 2 cols, o 2 filas por 4 cols, etc.). Quiero que este cambio de resolución suceda a través de la sumatoria. Necesito que esto funcione con grandes matrices, el número de filas, cols de la matriz más pequeña siempre será un factor de la matriz más grande.

La reducción de la matriz anterior a una matriz de 2 por 2 resultaría en (que es lo que quiero):

[[ 14. 22.] 
[ 46. 54.]] 

Tengo esta función que lo hace muy bien:

import numpy as np 

def shrink(data, rows, cols): 
    shrunk = np.zeros((rows,cols)) 
    for i in xrange(0,rows): 
     for j in xrange(0,cols): 
      row_sp = data.shape[0]/rows 
      col_sp = data.shape[1]/cols 
      zz = data[i*row_sp : i*row_sp + row_sp, j*col_sp : j*col_sp + col_sp] 
      shrunk[i,j] = np.sum(zz) 
    return shrunk 

print shrink(a,2,2) 
print shrink(a,2,1) 
#correct output: 
[[ 14. 22.] 
[ 46. 54.]] 
[[ 36.] 
[ 100.]] 

I' he echado un vistazo largo a través del examples, pero no puedo encontrar nada que ayude.

¿Hay una forma más rápida de hacerlo, sin necesidad de los bucles?

+0

Si funciona bien, ¿cuál es su pregunta? –

+0

@Niek de Klein - editado para aclarar. Estoy buscando un método más rápido para hacer esto. – fraxel

+0

Las personas que desean hacer este tipo de cosas tienden a usar el módulo 'itertools', podría valer la pena echarle un vistazo. – heltonbiker

Respuesta

21

Con su ejemplo:

a.reshape(2,2,2,2).sum(axis=1).sum(axis=2) 

devuelve:

array([[14, 22], 
     [46, 54]]) 

Ahora vamos a crear una función general ...

def shrink(data, rows, cols): 
    return data.reshape(rows, data.shape[0]/rows, cols, data.shape[1]/cols).sum(axis=1).sum(axis=2) 

obras para sus ejemplos:

In [19]: shrink(a, 2,2) 
Out[19]: 
array([[14, 22], 
     [46, 54]]) 

In [20]: shrink(a, 2,1) 
Out[20]: 
array([[ 36], 
     [100]]) 
+0

Esto es asombrosamente "Numpythonic". – heltonbiker

+0

(+1) ¡Inteligente! ... – NPE

+0

¡Exactamente lo que estaba buscando gracias! – fraxel

3

Estoy seguro de que es un enfoque mejor/más inteligente sin todos estos bucles horrendos ...

Aquí es una manera de evitar de manera explícita bucle sobre todos los elementos de data:

def shrink(data, rows, cols): 
    row_sp = a.shape[0]/rows 
    col_sp = a.shape[1]/cols 
    tmp = np.sum(data[i::row_sp] for i in xrange(row_sp)) 
    return np.sum(tmp[:,i::col_sp] for i in xrange(col_sp)) 

En mi máquina, esto es aproximadamente un 30% más rápido que su versión (para shrink(a, 2, 2)).

+0

+1 muchas gracias, buena manera de hacerlo, pero eumiro clavó esta. – fraxel

Cuestiones relacionadas