Juro que esto debería ser tan fácil… ¿por Qué no es? 🙁

De hecho, quiero combinar 2 partes de la misma matriz para realizar una serie compleja:

Data[:,:,:,0] , Data[:,:,:,1]

Estos no funcionan:

x = np.complex(Data[:,:,:,0], Data[:,:,:,1])
x = complex(Data[:,:,:,0], Data[:,:,:,1])

Que me estoy perdiendo algo? ¿Numpy no como la realización de las funciones de matriz de números complejos? Aquí está el error:

TypeError: only length-1 arrays can be converted to Python scalars
InformationsquelleAutor Duncan Tait | 2010-04-08

8 Comentarios

  1. 64

    Esto parece hacer lo que quieras:

    numpy.apply_along_axis(lambda args: [complex(*args)], 3, Data)

    Aquí hay otra solución:

    # The ellipsis is equivalent here to ":,:,:"...
    numpy.vectorize(complex)(Data[...,0], Data[...,1])

    Y, sin embargo, otra solución más simple:

    Data[...,0] + 1j * Data[...,1]

    PS: Si desea guardar la memoria (sin intermedio de la matriz):

    result = 1j*Data[...,1]; result += Data[...,0]

    desarrolladores de la solución a continuación también es rápido.

    • Mismo error, me temo: TypeError: sólo la longitud-1 matrices pueden ser convertidos a Python Escalares
    • He actualizado la respuesta original después de realizar la prueba. Parece estar funcionando, ahora.
    • gracias mucho que trabajar. Es MUY lento, aunque (como es de esperar – como no es realmente una colección de la función), se tarda 5 segundos en cada bucle de ahora, en lugar de 0.1
    • He añadido otras dos soluciones: puede ser vale la pena el tiempo ellos también. Si esto funciona para usted, por favor, pulgar arriba la respuesta!
    • Excelentes ambos están mucho más rápido 🙂
    • -1, la apply_along_axis y vectorización solución es unidiomatic. El uso nativo de numpy ufuncs es idiomáticas y mucho más rápido.
    • Estoy de acuerdo en que las dos primeras soluciones que propone no son tan buenas como la última, pero ¿qué mejor solución con ufuncs qué tienes en mente? Por favor, comparta (posiblemente en una respuesta)!
    • La última solución es buena y idiomáticas, pero los desarrolladores de la solución en la respuesta de abajo es el más eficiente, ya que se evita la innecesaria intermedios.
    • los desarrolladores de la idea es realmente interesante, ya que se evita una creación de la matriz. (Todavía no entiendo la relación con ufuncs, sin embargo.)
    • Yo no era suficientemente específica, lo siento. Quería decir que es eficaz el uso de la incorporada en el ufuncs (en nuestro caso + y *), pero no es muy eficaz el uso de vectorización o apply_along_axis, como el bucle, a continuación, en general sucede en Python.
    • Veo, gracias. De hecho, la vectorize() enfoque es lento en comparación con las soluciones que seguir.
    • +1, la última edición de hecho me gusta la respuesta.

  2. 35

    Hay, por supuesto, los más que obvios:

    Data[...,0] + 1j * Data[...,1]
    • También Data.view(complex)
  3. 20

    Si sus partes reales e imaginarias son las rodajas a lo largo de la última dimensión y su matriz está contiguo a lo largo de la última dimensión, usted puede hacer

    A.view(dtype=np.complex128)

    Si usted está utilizando una sola precisión de la flota, este sería

    A.view(dtype=np.complex64)

    Aquí es un ejemplo más completo

    import numpy as np
    from numpy.random import rand
    # Randomly choose real and imaginary parts.
    # Treat last axis as the real and imaginary parts.
    A = rand(100, 2)
    # Cast the array as a complex array
    # Note that this will now be a 100x1 array
    A_comp = A.view(dtype=np.complex128)
    # To get the original array A back from the complex version
    A = A.view(dtype=np.float64)

    Si usted quiere deshacerse de la dimensión extra que se mantiene alrededor de la fundición, se podría hacer algo como

    A_comp = A.view(dtype=np.complex128)[...,0]

    Esto funciona porque, en la memoria, un número complejo es realmente sólo dos números de punto flotante. La primera representa la parte real, y el segundo representa la parte imaginaria.
    El punto de vista del método de la matriz de cambios de la dtype de la matriz para reflejar que usted desea para tratar al lado dos valores de punto flotante como un único número complejo y actualizaciones de la dimensión en consecuencia.

    Este método no copia los valores de la matriz o realizar nuevos cálculos, todo lo que hace es crear un nuevo objeto array que las vistas de un mismo bloque de memoria de manera diferente.
    Que hace que esta operación puede realizarse mucho más rápido que cualquier cosa que implica copiar los valores.
    También significa que los cambios realizados en los valores complejos de la matriz serán los reflejados en la matriz con las partes real e imaginaria.

    También puede ser un poco complicado para recuperar la matriz original si se quita el eje adicional que hay inmediatamente después de la conversión de tipo.
    Cosas como A_comp[...,np.newaxis].view(np.float64) actualmente no trabajo porque, a partir de este escrito, NumPy no detecta que la matriz es todavía C-contiguo cuando el eje de nuevo es añadido.
    Ver este problema.
    A_comp.view(np.float64).reshape(A.shape) que parece funcionar en la mayoría de los casos, aunque.

    • +1: Muy lúcida explicación de las limitaciones del método. Es posible que desee agregar explícitamente otra limitación (memoria compartida entre A_comp y A), y también una de las ventajas de este método (velocidad).
    • Gracias. He actualizado la respuesta en consecuencia.
  4. 13

    Esto es lo que estamos buscando:

    from numpy import array
    
    a=array([1,2,3])
    b=array([4,5,6])
    
    a + 1j*b
    
    ->array([ 1.+4.j,  2.+5.j,  3.+6.j])
    • Esta es sólo una parcial duplicado de las respuestas anteriores como Pierre de GM o de la mía: creo que su único efecto es el de tomar el tiempo de la gente, casi sin valor añadido (más allá del ejemplo), por lo que me permito sugerir que usted la elimine.
  5. 9

    Soy novato en python por lo que este puede no ser el método más eficiente, pero, si entiendo la intención de la pregunta correctamente, los pasos que se enumeran a continuación trabajó para mí.

    >>> import numpy as np
    >>> Data = np.random.random((100, 100, 1000, 2))
    >>> result = np.empty(Data.shape[:-1], dtype=complex)
    >>> result.real = Data[...,0]; result.imag = Data[...,1]
    >>> print Data[0,0,0,0], Data[0,0,0,1], result[0,0,0]
    0.0782889873474 0.156087854837 (0.0782889873474+0.156087854837j)
    • Interesante idea. Sin embargo, la pregunta es acerca de la combinación de Data[:,:,:,0] y Data[:,:,:,1] (más complicado que tu a). También, en lugar de utilizar zeros(), usted debe utilizar el más rápido y más adecuado empty().
    • La he comparado con los Datos[…,0] + 1j * Datos[…,1] solución. Con Datos = aleatorio.rand(100,100,1000,2),c=zeros(un.forma[:-1],dtype=complejo);c.real = Datos[…,0]; c.imag = Datos[…,1]; es 2x más rápido que el sencillo de Datos[…,0] + 1j * Datos[…,1]. Sorprendentemente, el efecto de la utilización de vacío en lugar de ceros fue insignificante.
    • +1. Nota: tengo la misma velocidad, con una variación de mi última respuesta: result = 1j*Data[...,1]; result += Data[...,0]. Esta respuesta es más natural, sin embargo, si una sola fórmula no se utiliza.
    • Creo que esta es la mejor respuesta, porque la intención es obvia al leer el código; Eric respuestas, mientras que funcionalmente correcto, son menos claros cuando la lectura de la espalda sobre el código.
  6. 3
    import numpy as np
    
    n = 51 #number of data points
    # Suppose the real and imaginary parts are created independently
    real_part = np.random.normal(size=n)
    imag_part = np.random.normal(size=n)
    
    # Create a complex array - the imaginary part will be equal to zero
    z = np.array(real_part, dtype=complex)
    # Now define the imaginary part:
    z.imag = imag_part
    print(z)
  7. 0

    Si usted realmente quiere ganarse el rendimiento (con grandes matrices), numexpr puede ser utilizado, que se aprovecha de múltiples núcleos.

    De instalación:

    >>> import numpy as np
    >>> Data = np.random.randn(64, 64, 64, 2)
    >>> x, y = Data[...,0], Data[...,1]

    Con numexpr:

    >>> import numexpr as ne
    >>> %timeit result = ne.evaluate("complex(x, y)")
    573 µs ± 21.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

    Comparación con el rápido numpy método:

    >>> %timeit result = np.empty(x.shape, dtype=complex); result.real = x; result.imag = y
    1.39 ms ± 5.74 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
  8. -1

    Que trabajó para mí:

    de entrada:

    [complex(a,b) for a,b in zip([1,2,3],[1,2,3])]

    de salida:

    [(1+4j), (2+5j), (3+6j)]
    • -1, esto deja a la parte imaginaria igual a cero
    • Verificación actualizada de la aplicación.

Dejar respuesta

Please enter your comment!
Please enter your name here