2012-02-12 16 views
22

Penso che il mio problema dovrebbe essere molto semplice, ma non riesco a trovare alcun aiuto su Internet. Sono molto nuovo a Python, quindi è possibile che mi manchi qualcosa di molto ovvio.Python: ridimensionare una matrice esistente e riempire di zeri

Ho un array, S, come questo [x x x] (one-dimensional). Creo ora una matrice diagonale , sigma, con np.diag(S) - finora, tutto bene. Ora, voglio ridimensionare questo nuovo array diagonale in modo che possa moltiplicarlo per un altro array che ho .

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? 

Tuttavia, quando stampo il contenuto di my_sigma, ottengo "None". Qualcuno può per favore indicarmi la direzione giusta, perché non posso immaginare che questo dovrebbe essere così complicato.

Grazie in anticipo per qualsiasi aiuto!

Casper

grafica:

ho questo:

[x x x] 

voglio che questo:

[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

Stai definendo shape(), diag() e ridimensiona(), o sono quelli di una libreria che stai utilizzando? – grieve

+0

resize() proviene dalla libreria numpy, avrei dovuto specificarlo. – casper

+0

Questo è numpy, giusto? Se sto capendo correttamente, sigma contiene dei dati, ma tu vuoi rendere sigma più grande e zero riempire i nuovi elementi. È corretto? Se hai solo bisogno di un nuovo array a riempimento zero, usa 'numpy.zeros ((6,6))' – gfortune

risposta

17

sigma.resize() rendimenti None perché opera sul posto. np.resize(sigma, shape), d'altra parte, restituisce il risultato ma anziché il riempimento con zeri, esso si applica con le ripetizioni dell'array.

Inoltre, la funzione shape() restituisce la forma dell'input. Se vuoi semplicemente predefinire una forma, usa solo 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 

Tuttavia, questo sarà prima appiattirsi l'array originale, e poi ricostruirlo nella forma data, distruggendo l'ordinamento originale. Se si desidera "eseguire il pad" con zeri, invece di utilizzare resize() è possibile indicizzare direttamente in una matrice zero generata.

# 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

Grazie, questo è molto vicino a quello di cui ho bisogno, ma ora la mia nuova matrice perde la sua diagonalità, cioè gli elementi che erano originariamente lungo la diagonale non rimangono lì. Qualche idea su come risolvere questo problema? – casper

+0

@Casper: vedere la mia modifica. – voithos

+0

Grazie! Questo è perfetto, grazie per tutto il tuo sforzo, voithos! – casper

4

Vedo la modifica ... è necessario prima creare gli zeri e quindi spostare alcuni numeri in esso. np.diag_indices_from potrebbe essere utile per voi

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

Anche questo sembra funzionare, grazie! Sono contento di vedere che è un processo abbastanza complicato e che non mi mancava solo qualcosa. – casper

+0

Mi piace di più. Più leggibile e aggiunge solo tutto ciò che è necessario. Inoltre, usare 'sigma.dtype' è una buona idea. – voithos

+0

Immagino che il contesto della domanda sia quello di un SVD di una matrice rettangolare (con 'full_matrices = True'), e che effettui la ricostruzione' A = USV''. In tal caso, preferirei questo tipo di soluzione. – Patrick

48

c'è una nuova funzione NumPy nella versione 1.7.0 numpy.pad che può fare questo in una sola linea. Come le altre risposte, puoi costruire la matrice diagonale con np.diag prima del padding. La tupla ((0,N),(0,0)) utilizzata in questa risposta indica il "lato" della matrice da eseguire.

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 è ora pari a:

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

** Grazie per aver postato una risposta di aggiornamento **. Prima del mio +1 le nostre risposte erano legate ma la mia era pre-numpy 1.7. Non sei sicuro di ottenere la risposta migliore perché StackOverflow ha un bias "la prima risposta vince". Bello vedere nuove informazioni ... –

0

Un'altra soluzione python puro è

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 è ora

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

è una soluzione orrendo, io ammettere t cappello. Tuttavia, illustra alcune funzioni del tipo list che è possibile utilizzare.

0

Questa soluzione funziona con resize funzione

Prendere una matrice campione

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

""" 

Questo dosent lavoro, è sufficiente aggiungere un valori ripetitori

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.]]) 
""" 

Questo fa lavoro

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

Se si modifica la seconda dimensione e non la prima, non sarà – bold

Problemi correlati