2012-05-25 27 views
13

Estoy en mi viaje de transición de MATLAB a scipy (+ numpy) + matplotlib. Sigo teniendo problemas al implementar algunas cosas. Quiero crear una matriz vectorial simple en tres partes diferentes. En MATLAB Me gustaría hacer algo como:creación de matriz numpy con una secuencia

vector=[0.2,1:60,60.8]; 

Esto se traduce en una matriz unidimensional de 62 posiciones. Estoy tratando de implementar esto usando scipy. Lo más cerca que estoy ahora es la siguiente:

a=[[0.2],linspace(1,60,60),[60.8]] 

Sin embargo, esto crea una lista, no una matriz, y por lo tanto no puedo darle forma a una matriz de vectores. Pero entonces, cuando hago esto, me sale un error

a=array([[0.2],linspace(1,60,60),[60.8]]) 
ValueError: setting an array element with a sequence. 

Creo que mi principal obstáculo es que no puedo encontrar la manera de traducir esta simple operación en MATLAB:

a=[1:2:20]; 

a numpy . Sé cómo hacerlo para acceder a las posiciones en una matriz, aunque no al crear una secuencia. ¡Cualquier ayuda será apreciada, gracias!

Respuesta

13

Bueno NumPy implementa la función de MATLAB matriz de creación, vector, utilizando dos funciones en lugar de uno - cada uno especifica implícitamente un eje en particular a lo largo de la cual concatenación debe ocurrir. Estas funciones son:

  • r_ (concatenación de modo de fila) y

  • c_ (por columnas)


Así que para su ejemplo , el equivalente de NumPy es:

>>> import numpy as NP 

>>> v = NP.r_[.2, 1:10, 60.8] 

>>> print(v) 
    [ 0.2 1. 2. 3. 4. 5. 6. 7. 8. 9. 60.8] 

La contraparte por columnas es:

>>> NP.c_[.2, 1:10, 60.8] 

rebanada funciona notación como se esperaba [inicio: Parada: paso]:

>>> v = NP.r_[.2, 1:25:7, 60.8] 

>>> v 
    array([ 0.2, 1. , 8. , 15. , 22. , 60.8]) 

Aunque si un número imaginario de utilizado como tercer argumento, la notación de corte se comporta como linspace:

>>> v = NP.r_[.2, 1:25:7j, 60.8] 

>>> v 
    array([ 0.2, 1. , 5. , 9. , 13. , 17. , 21. , 25. , 60.8]) 


De lo contrario, se comporta como arange:

>>> v = NP.r_[.2, 1:25:7, 60.8] 

>>> v 
    array([ 0.2, 1. , 8. , 15. , 22. , 60.8]) 
+0

gracias doug! eso es extremadamente genial, y está a dos caracteres de distancia para ser tan compacto como el matlab. ¡estupendo! – lllllll

+0

@ vint-i-vuit no hay problema. Si mi respuesta fue útil para usted, márquela como "aceptada" haciendo clic en la "marca de verificación", visible cuando pase el mouse sobre el puntaje en la esquina superior izquierda de mi respuesta. (O si otra respuesta fue más útil, obviamente querrás marcar esa en su lugar). Sí, son dos caracteres más, pero creo que vale la pena, así que NumPy puede tener una función para cada uno de los dos ejes para concatenar (r_ & c_). – doug

+0

no lo sabía, ¡sí!Aprendí mucho de todas las publicaciones, todas funcionan como yo quería, pero posiblemente la tuya sea la más cercana a MATLAB. ¡gracias a todos! – lllllll

5

Usted podría intentar algo como:

a = np.hstack(([0.2],np.linspace(1,60,60),[60.8])) 
+0

true! eso también funciona, gracias JoshAdel. Además, ¿es linspace la única opción cuando deseo hacer algo como a = [1: 2: 20]? Lo que implica que no sé el tamaño final del vector, solo el paso y los puntos de inicio/finalización. [bis] – lllllll

+1

Acabo de encontrarlo gracias a mgilson. La respuesta es rango (inicio, parada, paso). ¡estupendo! – lllllll

+0

@ vint-i-vuit Tenga en cuenta que la función de rango incorporado de python solo funciona para valores enteros. Numpy proporciona 'arange' que hará lo mismo (también con flotadores si así lo desea) devolviendo una matriz, pero la documentación indica que' linspace' es una mejor opción en la mayoría de los casos ya que (debido a la redondez), los resultados de 'arange' puede no ser exactamente lo que esperas. – mgilson

1

si entiendo el MATLAB correctamente, se podría lograr algo como esto usando:

a=np.array([0.2]+list(range(1,61))+[60.8]) 

Pero es probable que haya una mejor manera ... la list(range(1,61)) podría ser range(1,61) si está usando Python 2.X.

Esto funciona creando 3 listas y luego concatenándolas mediante el operador +.

La razón de su intento original no se debe trabajar

a=[ [0.2], np.linspace(1,60,60), [60.8] ] crea una lista de listas - en otras palabras:

a[0] == [0.2] #another list (length 1) 
a[1] == np.linspace(1,60,60) #an array (length 60) 
a[2] == [60.8] #another list (length 1) 

La función array espera un iterable que es una secuencia, o una secuencia de secuencias que tienen la misma longitud.

+0

¡gran mgilson! eso es probablemente lo más cercano a la sintaxis de MATLAB. Todavía no es tan compacto como a = [0.2,1: 60,60.8] pero genial. muchas gracias, ahora lo veo más claro. – lllllll

+0

Creo que encontrarás que aunque muchas cosas en 'numpy' son tan concisas como en matlab (y un par de cosas un poco más concisas), hay bastantes cosas que no son tan concisas. Sin embargo , En general, creo que el código es mucho más intuitivo. – mgilson

+0

Hasta ahora, la flexibilidad adquirida, especialmente en el trazado, es tan valiosa como la "menos concisión" de la sintaxis, hasta ahora. :) – lllllll

3
np.concatenate([[.2], linspace(1,60,60), [60.8]]) 
+0

maldita sea, cierto! eso funciona, gracias larsmans. Además, ¿es linspace la única opción cuando deseo hacer algo como a = [1: 2: 20]? Lo que implica que no sé el tamaño final del vector, solo el paso y los puntos de inicio/finalización. – lllllll

+1

Acabo de encontrarlo gracias a mgilson. El answe es rango (inicio, parada, paso). ¡estupendo! – lllllll

+1

También podría intentar 'np.arange (1,20,2)' aunque tenga cuidado ya que esta operación no incluye el último número del rango (por ejemplo, matriz ([1, 3, 5, 7, 9, 11, 13, 15, 17, 19])). Olvidé cómo Matlab maneja esto y hace tiempo que lo eliminé de mi máquina. – JoshAdel

2

de alguna manera como la idea de la construcción de estos rangos segmentados que usted ha mencionado. Si los usa mucho, tal vez una pequeña función como

import numpy as np 

def segrange(*args): 
    result = [] 
    for arg in args: 
     if hasattr(arg,'__iter__'): 
      result.append(range(*arg)) 
     else: 
      result.append([arg]) 
    return np.concatenate(result) 

que le da

>>> segrange(1., (2,5), (5,10,2)) 
[ 1. 2. 3. 4. 5. 7. 9.] 

sería bueno tener. Aunque, probablemente iría por la respuesta usando concatenate/hstack.

+0

¡es una buena idea! Creo que intentaré mantener el operador '+' usado en la respuesta de mgilson a partir de ahora, ya que es el que encuentro más cercano al matlab, por lo tanto, me resulta menos difícil recordarlo. Sin embargo, veré si la ejecución de ese código es más conveniente en algunos casos :) – lllllll

+1

Corrígeme si me equivoco, pero creo que 'isinstance (arg, list)' es preferible a 'type (arg) is list'. Además, podría acortar todo el bloque if a 'hasattr (arg, '__ iter __')' (y atrapar todo tipo de otros iterables mientras lo hace) – mgilson

+0

sí, su derecho mgilson. pero la respuesta de Doug poniendo _r reemplaza a todos ^^ – pwuertz

1

Eche un vistazo a np.r_.Básicamente es equivalente a lo que todos han sugerido, pero si vienes de matlab, es un poco más intuitivo (y si vienes de cualquier otro idioma, es un poco contra-intuitivo).

Como ejemplo, vector=[0.2,1:60,60.8]; se traduce en:

vector = np.r_[0.2, 1:61, 60.8] 
1

Sólo quiero señalar a cualquier otro pueblo que van de MATLAB para Numpy que se puede construir una matriz np.r_ con dos puntos y luego úsela al índice

Por ejemplo, si tiene en Matlab

arr_ones = ones(10,10) 

O en Numpy

arr_ones = np.ones([10,10]) 

Se podría en Matlab toma sólo las columnas 1 a 5, así como 7 así:

arr_ones(:,[1:5 7]) 

Hacer lo mismo en Numpy no es (al menos para mí) intuitivo. Esto le dará una "sintaxis no válida" error:

arr_ones[:,[1:5,7]] 

Sin embargo, esto funciona:

inds = np.r[1:5,] 
arr_ones[:,inds] 

Sé que esto no es técnicamente una nueva respuesta, pero con dos puntos para construir una matriz para indexar en una matriz parece tan natural en Matlab, estoy apostando a que muchas personas que vengan a esta página querrán saber esto. (Vine aquí en lugar de hacer una nueva pregunta.)

Cuestiones relacionadas