wake-up-neo.com

Numpy: Erstellen eines komplexen Arrays aus zwei echten Arrays?

Ich schwöre, das sollte so einfach sein ... Warum ist es nicht so? :(

In der Tat möchte ich zwei Teile des gleichen Arrays zu einem komplexen Array zusammenfassen:

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

Diese funktionieren nicht:

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

Fehlt mir etwas? Hat numpy nicht gern Array-Funktionen für komplexe Zahlen? Hier ist der Fehler:

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

Dies scheint zu tun, was Sie wollen:

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

Hier ist eine andere Lösung:

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

Und noch eine einfachere Lösung:

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

PS: Wenn Sie Speicherplatz sparen möchten (kein Zwischenarray):

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

die Lösung von devS ist ebenfalls schnell.

60
Eric O Lebigot

Es ist natürlich das ziemlich offensichtliche:

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

Wenn Ihr Real- und Imaginärteil die Schnitte entlang der letzten Dimension sind und Ihr Array entlang der letzten Dimension zusammenhängend ist, können Sie dies einfach tun

A.view(dtype=np.complex128)

Wenn Sie einzelne Präzisionsschwimmer verwenden, wäre dies der Fall

A.view(dtype=np.complex64)

Hier ist ein ausführlicheres Beispiel

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)

Wenn Sie die zusätzliche Dimension loswerden möchten, die vom Casting übrig bleibt, können Sie so etwas tun

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

Dies funktioniert, weil eine komplexe Zahl im Speicher nur zwei Fließkommazahlen ist. Der erste stellt den Realteil dar und der zweite den Imaginärteil. Die Ansichtsmethode des Arrays ändert den dtype des Arrays, um anzuzeigen, dass Sie zwei benachbarte Gleitkommawerte als eine einzige komplexe Zahl behandeln möchten, und aktualisiert den Dimension entsprechend.

Diese Methode kopiert keine Werte im Array und führt keine neuen Berechnungen aus. Sie erstellt lediglich ein neues Array-Objekt, das denselben Speicherblock unterschiedlich darstellt. Dies macht es so, dass diese Operation ausgeführt werden kann. viel schneller als alles andere, was das Kopieren von Werten betrifft ..__ Dies bedeutet auch, dass alle Änderungen, die im komplexwertigen Array vorgenommen werden, im Array mit den Real- und Imaginärteilen angezeigt werden.

Es kann auch etwas komplizierter sein, das ursprüngliche Array wiederherzustellen, wenn Sie die zusätzliche Achse entfernen, die unmittelbar nach der Typumwandlung vorhanden ist Funktionen wie A_comp[...,np.newaxis].view(np.float64) funktionieren derzeit nicht, da NumPy dies nicht erkennt Das Array ist immer noch C-zusammenhängend, wenn die neue Achse hinzugefügt wird . Siehe Dieses Problem .A_comp.view(np.float64).reshape(A.shape) scheint in den meisten Fällen zu funktionieren.

17
IanH

Das ist, wonach Sie suchen:

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

Ich bin Python-Anfänger, daher ist dies möglicherweise nicht die effizienteste Methode, aber wenn ich die Absicht der Frage richtig verstehe, haben die unten aufgeführten Schritte für mich funktioniert.

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

Wenn Sie wirklich Leistung erzielen möchten (mit großen Arrays), kann numexpr verwendet werden, wodurch mehrere Kerne genutzt werden.

Konfiguration:

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

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

Im Vergleich zur schnellen numpy-Methode:

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

Das hat für mich funktioniert:

Eingabe:

from scipy import *

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

Ausgabe:

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