2010-04-08 7 views
39

Je jure que ça devrait être si facile ... Pourquoi pas? :(Numpy: Création d'un tableau complexe à partir de 2 réels?

En fait, je veux combiner 2 parties du même tableau pour faire un ensemble complexe:

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

Ceux-ci ne fonctionnent pas:

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

Est-ce que je manque quelque chose? Est-ce que numpy ne ressemble pas à l'exécution de fonctions de tableau sur des nombres complexes? Voici l'erreur:

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

Répondre

50

Cela semble faire ce que vous voulez:

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

Voici une autre solution:

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

Et encore une autre solution plus simple:

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

PS: Si vous voulez économiser de la mémoire (aucun tableau intermédiaire):

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

La solution de devS ci-dessous est également rapide.

+0

même erreur que j'ai peur: TypeError: que des tableaux longueur-1 peuvent être convertis en Python Scalaires –

+0

@Duncan: Je mis à jour la réponse originale après avoir effectué le test. Cela semble fonctionner, maintenant. – EOL

+0

merci beaucoup qui fonctionne. C'est TRÈS lent (comme vous pouvez l'imaginer, car ce n'est pas vraiment une fonction numérique), cela prend 5 secondes par boucle au lieu de 0.1 –

0

Cela a fonctionné pour moi:

entrée :

from scipy import * 

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

sortie:

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

-1, ceci laisse la partie imaginaire égale à zéro –

26

Il y a bien sûr la assez évidente:

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

Aussi 'Data.view (complexe)' –

7

Je suis python novice donc ce n'est peut-être pas la méthode la plus efficace mais, si je comprends bien l'intention de la question, les étapes listées ci-dessous ont fonctionné pour moi.

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

Idée intéressante. Cependant, la question est de combiner 'Data [:,:,:, 0]' et 'Data [:,:,:, 1]' (plus compliqué que votre 'a'). Aussi, au lieu d'utiliser 'zeros()', vous devriez utiliser le 'empty()' plus rapide et plus approprié. – EOL

+0

Je l'ai comparé à la solution Data [..., 0] + 1j * Data [..., 1]. Avec Data = random.rand (100,100,1000,2), c = zéros (a.shape [: - 1], dtype = complexe); c.real = Data [..., 0]; c.imag = Data [..., 1]; est 2x plus rapide que les données simples [..., 0] + 1j * Data [..., 1]. Étonnamment, l'effet d'utiliser vide au lieu de zéros était négligeable. –

+1

+1. Note: j'obtiens la même vitesse avec une variation de ma dernière réponse: 'result = 1j * Data [..., 1]; résultat + = Données [..., 0] '. Cette réponse est plus naturelle, cependant, si une seule formule n'est pas utilisée. – EOL

11

C'est ce que vous êtes à la recherche pour:

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

Ce n'est qu'un duplicata partiel de réponses antérieures comme Pierre GM ou le mien: je pense que son seul effet est de prendre le temps des gens pour presque aucune valeur ajoutée (au-delà de l'exemple), donc je vous suggère de le supprimer. – EOL

14

Si vos parties réelles et imaginaires sont les tranches le long de la dernière dimension et votre tableau est contiguë le long de la dernière dimension, vous pouvez juste faire

A.view(dtype=np.complex128) 

Si vous utilisez des flotteurs de simple précision, ce serait

A.view(dtype=np.complex64) 

Voici un exemple plus complet

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 vous voulez vous débarrasser de la dimension supplémentaire qui reste autour de la coulée, vous pourriez faire quelque chose comme

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

Cela fonctionne parce que, mémoire, un nombre complexe est vraiment juste deux nombres à virgule flottante. Le premier représente la partie réelle et le second représente la partie imaginaire. La méthode view de la matrice modifie le dtype du tableau pour refléter le fait que vous voulez traiter deux valeurs à virgule flottante adjacentes en un seul nombre complexe et mettre à jour la dimension en conséquence.

Cette méthode ne copie aucune valeur dans le tableau ou effectuer de nouveaux calculs, tout ce qu'il fait est de créer un nouvel objet tableau qui considère différemment le même bloc de mémoire. Cela fait que cette opération peut être effectuée beaucoup plus rapidement que tout ce qui implique la copie de valeurs. Cela signifie également que toutes les modifications apportées au tableau à valeurs complexes seront reflétées dans le tableau avec les parties réelle et imaginaire.

Il peut aussi être un peu plus délicat pour récupérer le tableau original si vous supprimez l'axe supplémentaire qui est là immédiatement après la distribution de type. Des choses comme A_comp[...,np.newaxis].view(np.float64) ne fonctionnent pas actuellement car, au moment où j'écris, NumPy ne détecte pas que le tableau est toujours C-contigu lorsque le nouvel axe est ajouté. Voir this issue. A_comp.view(np.float64).reshape(A.shape) semble cependant fonctionner dans la plupart des cas.

+0

+1: Explication très claire des limites de la méthode. Vous pourriez vouloir ajouter explicitement une autre limitation (mémoire partagée entre 'A_comp' et' A'), et aussi un avantage de cette méthode (vitesse). – EOL

+0

@EOL Merci. J'ai mis à jour la réponse en conséquence. – 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) 
Questions connexes