2010-04-08 29 views
39

Juro que esto debería ser tan fácil ... ¿Por qué no? :(Numpy: ¿Crea una matriz compleja a partir de 2 reales?

De hecho, quiero combinar 2 partes de la misma matriz para hacer un complejo conjunto:

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

estos no funcionan:

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

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

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

Respuesta

50

Esto parece hacer lo que quiere:

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 gama intermedia):

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

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

+0

mismo error me temo: TypeError: única longitud-1 matrices pueden ser convertidos en Python escalares –

+0

@Duncan: He actualizado la respuesta original después de realizar la prueba. Parece estar funcionando, ahora. – EOL

+0

muchas gracias que funciona. Aunque es MUY lento (como cabría esperar, ya que en realidad no es una función numpy), demora 5 segundos por ciclo ahora en lugar de 0.1 –

0

que trabajó para mí:

de entrada:

from scipy import * 

array([[1,2],[3,2]]).astype(complex) 

de salida:

array([[ 1.+0.j, 2.+0.j], 
     [ 3.+0.j, 2.+0.j]]) 
+4

-1, esto deja la parte imaginaria igual a cero –

26

Hay, por supuesto, la más obvia:

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

También 'Data.view (complex)' –

7

Soy un principiante de Python, así que este puede no ser el método más eficiente pero, si entiendo correctamente la intención de la pregunta, los pasos que figuran a continuación me funcionaron.

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

Idea interesante. Sin embargo, la pregunta es sobre la combinación de 'Datos [:,:,:, 0]' y 'Datos [:,:,:, 1]' (más complicados que su 'a'). Además, en lugar de usar 'ceros()', debe usar 'empty()' más rápido y más apropiado. – EOL

+0

Lo comparé con la solución de Datos [..., 0] + 1j * Datos [..., 1]. Con Data = random.rand (100,100,1000,2), c = ceros (a.shape [: - 1], dtype = complex); c.real = Datos [..., 0]; c.imag = Datos [..., 1]; es 2 veces más rápido que los datos directos [..., 0] + 1j * Datos [..., 1]. Sorprendentemente, el efecto de usar vacíos en lugar de ceros era insignificante. –

+1

+1. Nota: Obtengo la misma velocidad con una variación de mi última respuesta: 'resultado = 1j * Datos [..., 1]; resultado + = Datos [..., 0] '. Esta respuesta es más natural, sin embargo, si no se usa una sola fórmula. – EOL

11

Esto es lo que estas 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]) 
+0

Esto es solo un duplicado parcial de respuestas anteriores como la de Pierre GM o la mía: creo que su único efecto es tomar el tiempo de la gente casi sin ningún valor agregado (más allá del ejemplo), por lo que le sugiero que lo elimine. – EOL

14

Si sus partes real e imaginaria son las rodajas a lo largo de la última dimensión y la matriz es contigua a lo largo de la última dimensión, puede simplemente hacer

A.view(dtype=np.complex128) 

Si está utilizando flotadores de precisión simple, esto 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 desea deshacerse de la dimensión extra que se mantiene alrededor de la fundición, que podría hacer algo como

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

Esto funciona porque, en memoria, un número complejo es realmente solo dos números de coma flotante. El primero representa la parte real, y el segundo representa la parte imaginaria. El método de vista de la matriz cambia el tipo de la matriz para reflejar que desea tratar dos valores de coma 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 ningún nuevo cálculo, todo lo que hace es crear un nuevo objeto de matriz que visualice el mismo bloque de memoria de forma diferente. Eso hace que esta operación se pueda realizar mucho más rápido que cualquier cosa que implique la copia de valores. También significa que cualquier cambio realizado en la matriz de valores complejos se reflejará en la matriz con las partes real e imaginaria.

También puede ser un poco más complicado recuperar la matriz original si elimina el eje adicional que está allí inmediatamente después del tipo de fundido. Cosas como A_comp[...,np.newaxis].view(np.float64) no funcionan actualmente porque, al momento de escribir esto, NumPy no detecta que la matriz sigue siendo C-contigua cuando se agrega el nuevo eje. Ver this issue. A_comp.view(np.float64).reshape(A.shape) parece funcionar en la mayoría de los casos sin embargo.

+0

+1: explicación muy lúcida 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 ventaja de este método (velocidad). – EOL

+0

@EOL Gracias. He actualizado la respuesta en consecuencia. – IanH

2
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) 
Cuestiones relacionadas