Numpy: ¿Creando una matriz compleja a partir de 2 reales?

Juro que esto debería ser tan fácil … ¿Por qué no? 🙁

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

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

Estos no funcionan:

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

¿Me estoy perdiendo de algo? ¿No le gusta a Npypy realizar funciones de matriz en números complejos? Aquí está el error:

 TypeError: only length-1 arrays can be converted to Python scalars 

Esto parece hacer lo que quieres:

 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 otra solución más simple:

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

PS : Si desea guardar memoria (sin matriz intermedia):

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

La solución de devS a continuación también es rápida.

Por supuesto, hay algo bastante obvio:

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

Si sus partes reales e imaginarias son los cortes a lo largo de la última dimensión y su matriz es contigua a lo largo de la última dimensión, simplemente puede hacer

 A.view(dtype=np.complex128) 

Si está utilizando flotadores de precisión simple, esto sería

 A.view(dtype=np.complex64) 

Aquí hay 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 desea deshacerse de la dimensión adicional que queda alrededor del casting, podría hacer algo como

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

Esto funciona porque, en la memoria, un número complejo es en realidad solo dos números de punto flotante. El primero representa la parte real, y el segundo representa la parte imaginaria. El método de vista de la matriz cambia el dtype de la matriz para reflejar que desea tratar dos valores de punto flotante adyacentes como un único número complejo y actualiza la dimensión en consecuencia.

Este método no copia ningún valor en la matriz ni realiza nuevos cálculos, todo lo que hace es crear un nuevo objeto de matriz que ve el mismo bloque de memoria de manera diferente. Eso lo hace para que esta operación se pueda realizar mucho más rápido que cualquier cosa que implique copiar valores. También significa que cualquier cambio realizado en la matriz de valores complejos se reflejará en la matriz con las partes reales e imaginarias.

También puede ser un poco más difícil recuperar la matriz original si elimina el eje adicional que está allí inmediatamente después del tipo de conversión. Cosas como A_comp[...,np.newaxis].view(np.float64) no funcionan actualmente porque, en el momento de esta escritura, NumPy no detecta que la matriz sigue siendo contigua a C cuando se agrega el nuevo eje. Ver este número . A_comp.view(np.float64).reshape(A.shape) parece funcionar en la mayoría de los casos.

Esto es lo que estás 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]) 

Soy un principiante de Python, por lo que puede que este no sea el método más eficiente, pero si entiendo correctamente la intención de la pregunta, los pasos que se enumeran a continuación me han funcionado.

 >>> 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) 
 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) 

Si realmente desea mejorar el rendimiento (con grandes arreglos), puede usar numexpr , lo que aprovecha los múltiples núcleos.

Preparar:

 >>> 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) 

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

 >>> %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) 

Eso funcionó para mí:

entrada:

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

salida:

 [(1+4j), (2+5j), (3+6j)]