Crear una matriz numpy con elementos en función de los índices.

¿Cómo puedo crear una matriz numpy con sus elementos como una función de sus índices? Por ejemplo, una tabla de multiplicar: a[i,j] = i*j

Un Un-numpy y un-pythonic sería crear una matriz de ceros y luego hacer un bucle.

No hay duda de que hay una mejor manera de hacerlo, sin un bucle.

Sin embargo, incluso mejor sería crear la matriz de inmediato.

Una solución genérica sería usar np.fromfunction ()

Desde el doc:

numpy.fromfunction(function, shape, **kwargs)

Construye una matriz ejecutando una función sobre cada coordenada. Por lo tanto, la matriz resultante tiene un valor fn (x, y, z) en la coordenada (x, y, z).

La línea de abajo debe proporcionar la matriz requerida.

numpy.fromfunction(lambda i, j: i*j, (5,5))

Salida:

 array([[ 0., 0., 0., 0., 0.], [ 0., 1., 2., 3., 4.], [ 0., 2., 4., 6., 8.], [ 0., 3., 6., 9., 12.], [ 0., 4., 8., 12., 16.]]) 

El primer parámetro de la función es un ejecutable que se ejecuta para cada una de las coordenadas. Si foo es una función que pasa como primer argumento, foo(i,j) será el valor en (i,j) . Esto vale también para dimensiones más altas. La forma de la matriz de coordenadas se puede modificar utilizando el parámetro de shape .

Aquí hay una forma de hacerlo:

 >>> indices = numpy.indices((5, 5)) >>> a = indices[0] * indices[1] >>> a array([[ 0, 0, 0, 0, 0], [ 0, 1, 2, 3, 4], [ 0, 2, 4, 6, 8], [ 0, 3, 6, 9, 12], [ 0, 4, 8, 12, 16]]) 

Para explicar con más numpy.indices((5, 5)) , numpy.indices((5, 5)) genera dos matrices que contienen los índices x e y de una matriz de 5×5, así:

 >>> numpy.indices((5, 5)) array([[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4]], [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]]) 

Cuando multiplicas estas dos matrices, numpy multiplica el valor de las dos matrices en cada posición y devuelve el resultado.

Para la multiplicación

 np.multiply.outer(np.arange(5), np.arange(5)) # a_ij = i * j 

y en general

 np.frompyfunc( lambda i, j: f(i, j), 2, 1 ).outer( np.arange(5), np.arange(5), ).astype(np.float64) # a_ij = f(i, j) 

básicamente creas un np.ufunc través de np.frompyfunc y luego lo np.frompyfunc con los índices.

Editar

Comparación de la velocidad entre las diferentes soluciones.

Matrices pequeñas:

 Eyy![1]: %timeit np.multiply.outer(np.arange(5), np.arange(5)) 100000 loops, best of 3: 4.97 µs per loop Eyy![2]: %timeit np.array( [ [ i*j for j in xrange(5)] for i in xrange(5)] ) 100000 loops, best of 3: 5.51 µs per loop Eyy![3]: %timeit indices = np.indices((5, 5)); indices[0] * indices[1] 100000 loops, best of 3: 16.1 µs per loop 

Matrices más grandes:

 Eyy![4]: %timeit np.multiply.outer(np.arange(4096), np.arange(4096)) 10 loops, best of 3: 62.4 ms per loop Eyy![5]: %timeit indices = np.indices((4096, 4096)); indices[0] * indices[1] 10 loops, best of 3: 165 ms per loop Eyy![6]: %timeit np.array( [ [ i*j for j in xrange(4096)] for i in xrange(4096)] ) 1 loops, best of 3: 1.39 s per loop 

Estoy lejos de mi python en este momento, ¿pero funciona esto?

 array( [ [ i*j for j in xrange(5)] for i in xrange(5)] ) 

Solo quería agregar que la respuesta de @ Senderle se puede generalizar para cualquier función y dimensión:

 dims = (3,3,3) #i,j,k ii = np.indices(dims) 

Entonces podrías calcular a[i,j,k] = i*j*k como

 a = np.prod(ii,axis=0) 

o a[i,j,k] = (i-1)*j*k :

 a = (ii[0,...]-1)*ii[1,...]*ii[2,...] 

etc