web-dev-qa-db-fra.com

Numpy: Créer un tableau complexe à partir de 2 réels?

Je jure que cela devrait être si facile ... Pourquoi n'est-ce pas? :(

En fait, je veux combiner 2 parties du même tableau pour en faire un tableau 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? Numpy n'aime-t-il pas exécuter des fonctions de tableau sur des nombres complexes? Voici l'erreur:

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

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 souhaitez économiser de la mémoire (pas de tableau intermédiaire):

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

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

60
Eric O Lebigot

Il y a bien sûr le plus évident:

Data[...,0] + 1j * Data[...,1]
34
Pierre GM

Si vos parties réelles et imaginaires sont les coupes de la dernière dimension et que votre tableau est contigu le long de la dernière dimension, vous pouvez simplement le faire.

A.view(dtype=np.complex128)

Si vous utilisez des flotteurs 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 après le casting, vous pouvez faire quelque chose comme:

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

Cela fonctionne car, en mémoire, un nombre complexe n'est en réalité que deux nombres à virgule flottante. Le premier représente la partie réelle et le second représente la partie imaginaire . La méthode d'affichage du tableau modifie le type de ce tableau pour indiquer que vous souhaitez traiter deux valeurs à virgule flottante adjacentes comme un seul nombre complexe et mettre à jour le dimension en conséquence.

Cette méthode ne copie aucune valeur dans le tableau et n’effectue aucun nouveau calcul, elle crée un nouvel objet tableau qui affiche le même bloc de mémoire différemment . Cela permet à cette opération de pouvoir être exécutée beaucoup plus rapidement que tout ce qui implique la copie de valeurs ..__ Cela signifie également que toute modification apportée au tableau à valeurs complexes sera reflétée dans le tableau avec les parties réelle et imaginaire.

Il peut également s'avérer un peu plus délicat de récupérer le tableau d'origine si vous supprimez l'axe supplémentaire qui se trouve juste après le transtypage . Des choses comme A_comp[...,np.newaxis].view(np.float64) ne fonctionnent pas actuellement car, à la date de cette écriture, NumPy ne détecte pas que le tableau est toujours contigu au C lorsque le nouvel axe est ajouté .Voir ce problème .A_comp.view(np.float64).reshape(A.shape) semble fonctionner dans la plupart des cas.

17
IanH

Voici ce que vous recherchez:

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])
13
nadapez

Comme je suis novice en python, cette méthode n’est peut-être pas la plus efficace, mais si je comprends bien l’objet de la question, les étapes 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)
7
devS
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)
3

Si vous voulez vraiment améliorer les performances (avec de grands tableaux), vous pouvez utiliser numexpr , qui tire parti de plusieurs cœurs.

Installer:

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

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

Par rapport à la méthode rapide 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)
0
jawknee

Cela a fonctionné pour moi:

contribution:

from scipy import *

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

sortie:

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