2012-02-12 32 views
22

Creo que mi problema debería ser muy simple, sin embargo, no puedo encontrar ninguna ayuda en Internet en absoluto. Soy muy nuevo en Python, por lo que es posible que Me falta algo muy obvio.Python: cambiar el tamaño de una matriz existente y llenar con ceros

Tengo una matriz, S, como esta [x x x] (one-dimensional). Ahora creo una matriz diagonal , sigma, con np.diag(S) - hasta ahora, muy bien. Ahora, quiero redimensionar esta nueva matriz diagonal para que pueda multiplicarla por otra matriz que tenga .

import numpy as np 
... 
shape = np.shape((6, 6)) #This will be some pre-determined size 
sigma = np.diag(S) #diagonalise the matrix - this works 
my_sigma = sigma.resize(shape) #Resize the matrix and fill with zeros - returns "None" - why? 

Sin embargo, al imprimir el contenido de my_sigma, me sale "None". ¿Puede alguien por favor señalarme en la dirección correcta, porque no puedo imaginar que esto debería ser tan complicado.

¡Gracias de antemano por cualquier ayuda!

Casper

gráfica:

tengo esto:

[x x x] 

quiero esto:

[x 0 0] 
[0 x 0] 
[0 0 x] 
[0 0 0] 
[0 0 0] 
[0 0 0] - or some similar size, but the diagonal elements are important. 
+0

¿Está definiendo shape(), diag() y resize(), o son los de una biblioteca que está utilizando? – grieve

+0

resize() es de la biblioteca numpy, debería haber especificado eso. – casper

+0

Esto es numpy, ¿verdad? Si estoy entendiendo correctamente, sigma tiene datos, pero quieres hacer que sigma sea más grande y llenar los nuevos elementos. ¿Es eso correcto? Si solo necesita una nueva matriz con cero relleno, use 'numpy.zeros ((6,6))' – gfortune

Respuesta

17

sigma.resize() vuelve None porque opera en el lugar. np.resize(sigma, shape), por otro lado, devuelve el resultado pero en lugar de relleno con ceros, almohadillas con repeticiones de la matriz.

Además, la función shape() devuelve la forma de la entrada. Si solo quieres predefinir una forma, solo usa una tupla.

import numpy as np 
... 
shape = (6, 6) #This will be some pre-determined size 
sigma = np.diag(S) #diagonalise the matrix - this works 
sigma.resize(shape) #Resize the matrix and fill with zeros 

Sin embargo, esto va primero aplanar su matriz original, y luego reconstruirlo en la forma dada, destruyendo el orden original. Si solo desea "rellenar" con ceros, en lugar de usar resize(), puede indexar directamente en una matriz cero generada.

# This assumes that you have a 2-dimensional array 
zeros = np.zeros(shape, dtype=np.int32) 
zeros[:sigma.shape[0], :sigma.shape[1]] = sigma 
+0

Gracias, esto está muy cerca de lo que necesito, pero ahora mi nueva matriz pierde su diagonales, es decir, los elementos que originalmente estaban a lo largo de la diagonal no permanecen allí. ¿Algúna idea de cómo arreglar esto? – casper

+0

@Casper: Ver mi edición. – voithos

+0

Gracias! Esto es perfecto, gracias por todo tu esfuerzo, voithos! – casper

4

Veo la edición ... tienes que crear los ceros primero y luego mover algunos números dentro. np.diag_indices_from podría ser útil para usted

bigger_sigma = np.zeros(shape, dtype=sigma.dtype) 
diag_ij = np.diag_indices_from(sigma) 
bigger_sigma[diag_ij] = sigma[diag_ij] 
+0

Esto parece funcionar también, ¡gracias! Me alegra ver que es un proceso bastante complicado y que no solo me estaba perdiendo algo. – casper

+0

Me gusta esto mejor. Más legible y solo agrega lo que sea necesario. Además, usar 'sigma.dtype' es una buena idea. – voithos

+0

Supongo que el contexto de la pregunta es el de una SVD de una matriz rectangular (con 'full_matrices = True'), y hacer la reconstrucción' A = USV''. En ese caso, preferiría este tipo de solución. – Patrick

48

hay una nueva función numpy en la versión 1.7.0 numpy.pad que puede hacer esto en una sola línea. Al igual que las otras respuestas, puede construir la matriz diagonal con np.diag antes del relleno. La tupla ((0,N),(0,0)) utilizada en esta respuesta indica el "lado" de la matriz que se debe rellenar.

import numpy as np 

A = np.array([1, 2, 3]) 

N = A.size 
B = np.pad(np.diag(A), ((0,N),(0,0)), mode='constant') 

B es ahora igual a:

[[1 0 0] 
[0 2 0] 
[0 0 3] 
[0 0 0] 
[0 0 0] 
[0 0 0]] 
+1

** Gracias por publicar una respuesta de actualización **. Antes de mi +1, nuestras respuestas estaban vinculadas, pero la mía era previa numpy 1.7. No estoy seguro de que alguna vez llegue a la respuesta principal porque StackOverflow tiene un sesgo de "primera respuesta gana". Es bueno ver nueva información ... –

0

Otra solución pitón puro es

a = [1, 2, 3] 
b = [] 
for i in range(6): 
    b.append((([0] * i) + a[i:i+1] + ([0] * (len(a) - 1 - i)))[:len(a)]) 

b es ahora

[[1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 0, 0], [0, 0, 0], [0, 0, 0]] 

es una solución horrible, me quedo admitir t sombrero. Sin embargo, ilustra algunas funciones del tipo list que se pueden usar.

0

Esta solución funciona con resize función

Tomar una matriz de muestras

S= np.ones((3)) 
print (S) 
# [ 1. 1. 1.] 
d= np.diag(S) 
print(d) 
""" 
[[ 1. 0. 0.] 
[ 0. 1. 0.] 
[ 0. 0. 1.]] 

""" 

Este dosent trabajo, sólo tiene que añadir un archivo de valores que se repiten

np.resize(d,(6,3)) 
""" 
adds a repeating value 
array([[ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.], 
     [ 1., 0., 0.], 
     [ 0., 1., 0.], 
     [ 0., 0., 1.]]) 
""" 

Este lo hace trabajo

d.resize((6,3),refcheck=False) 
print(d) 
""" 
[[ 1. 0. 0.] 
[ 0. 1. 0.] 
[ 0. 0. 1.] 
[ 0. 0. 0.] 
[ 0. 0. 0.] 
[ 0. 0. 0.]] 
""" 
+0

Si cambia la segunda dimensión y no la primera, no lo hará – bold

Cuestiones relacionadas