Soru Numpy: 2 gerçek olandan karmaşık bir dizi oluşturma?


Yemin ederim ki bu kadar kolay olmalı ... Neden olmasın? :(

Aslında, karmaşık bir dizi yapmak için aynı dizinin 2 parçasını birleştirmek istiyorum:

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

Bunlar çalışmıyor:

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

Bir şey mi eksik? Numpy karmaşık sayılarda dizi işlevlerini gerçekleştirmekten hoşlanmaz mı? İşte hata:

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

44
2018-04-08 09:22


Menşei




Cevaplar:


Bu senin istediğin gibi görünüyor:

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

İşte başka bir çözüm:

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

Ve yine başka bir çözüm:

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

PS: Hafızayı kaydetmek istiyorsanız (ara sıra yok):

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

Aşağıda devS 'çözümü de hızlı.


55
2018-04-08 09:38



Korkarım aynı hata: TypeError: sadece uzunluk-1 diziler Python Scalars dönüştürülebilir - Duncan Tait
@Duncan: Testi yaptıktan sonra orijinal cevabı güncelledim. Şu an çalışıyor gibi görünüyor. - Eric Lebigot
teşekkürler çok işe yarıyor. ÇOK yavaş olsa (beklediğiniz gibi - gerçekten bir numpy işlevi olmadığı gibi), şimdi 0.1 yerine döngü başına 5 saniye sürüyor - Duncan Tait
@Duncan: İki tane başka çözüm daha ekledim: Onları da zamanlamaya değer. Eğer bu sizin için işe yararsa, lütfen cevabı alın! - Eric Lebigot
Mükemmel ikisi de çok daha hızlı :) - Duncan Tait


Elbette oldukça açık:

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

28
2017-09-05 19:34



Ayrıca Data.view(complex) - Bi Rico


Gerçek ve hayali parçalarınız son boyuttaki dilimlerdeyse ve diziniz son boyut boyunca bitişik ise, bunu yapabilirsiniz.

A.view(dtype=np.complex128)

Tek hassas yüzer kullanıyorsanız, bu olurdu

A.view(dtype=np.complex64)

İşte daha dolu bir örnek

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)

Eğer dökümden kalan ekstra boyuttan kurtulmak istiyorsanız,

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

Bu, bellekte karmaşık bir sayının gerçekten sadece iki kayan nokta sayısı olduğu için çalışır. Birincisi gerçek kısmı temsil ediyor, ikincisi ise hayali parçayı temsil ediyor. Dizinin görünüm yöntemi, dizinin dtype'ını iki bitişik kayan nokta değerini tek bir karmaşık sayı olarak işlemek istediğinizi yansıtacak şekilde değiştirir ve boyutu buna göre güncelleştirir.

Bu yöntem, dizideki herhangi bir değeri kopyalamaz veya herhangi bir yeni hesaplama yapmaz, hepsi aynı bellek bloğunu farklı şekilde görüntüleyen yeni bir dizi nesnesi oluşturur. Bu, bu işlemin yapılabilmesini sağlar çok değerleri kopyalamayı içeren her şeyden daha hızlı. Ayrıca karmaşık değerli dizide yapılan değişikliklerin diziye gerçek ve sanal bölümlerle yansıtılacağı anlamına gelir.

Ayrıca, dökümden hemen sonra var olan ekstra ekseni kaldırırsanız, orijinal diziyi kurtarmak biraz daha zor olabilir. Gibi şeyler A_comp[...,np.newaxis].view(np.float64) Şu anda çalışmıyor, çünkü bu yazıdan itibaren, NumPy yeni eksen eklendiğinde dizinin hala C-bitişik olduğunu algılamıyor. Görmek bu konu. A_comp.view(np.float64).reshape(A.shape) Yine de çoğu durumda gibi görünüyor.


15
2018-02-24 18:51



+1: Yöntemin sınırlamalarının çok açık bir açıklaması. Açıkça başka bir sınırlama eklemek isteyebilirsiniz. A_comp ve A) ve ayrıca bu yöntemin bir avantajı (hız). - Eric Lebigot
@EOL Teşekkürler. Cevabı buna göre güncelledim. - IanH


Aradığın şey bu:

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
2018-01-06 17:09



Bu, Pierre GM'nin veya benimki gibi önceki cevapların sadece bir kısmi kopyasıdır: Bence tek etkisinin, insanların neredeyse hiçbir katma değer (örneğin ötesindeki) için zaman alması olduğunu düşünüyorum, bu yüzden onu silmenizi öneririm. - Eric Lebigot


Ben python acemi oldum, bu en etkili yöntem olmayabilir, ancak sorunun doğru niyetini anlarsam, aşağıda listelenen adımlar benim için çalıştı.

>>> 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
2017-10-28 18:48



İlginç fikir. Ancak, soru birleştirmekle ilgili Data[:,:,:,0] ve Data[:,:,:,1] (seninkinden daha karmaşık a). Ayrıca, kullanmak yerine zeros()Daha hızlı ve daha uygun kullanmalısınız empty(). - Eric Lebigot
Veri […, 0] + 1j * Data […, 1] çözümü ile karşılaştırdım. Data = random.rand (100,100,1000,2) ile, c = sıfır (a.shape [: - 1], dtype = karmaşık); c.real = Veri [..., 0]; c.imag = Veri [..., 1]; basit verilerden 2 kat daha hızlıdır […, 0] + 1j * Veri […, 1]. Şaşırtıcı şekilde, sıfır yerine boş kullanmanın etkisi ihmal edilebilir düzeydeydi. - Pavel Bazant
+1. Not: Son hızımın bir çeşidi ile aynı hızı elde ediyorum: result = 1j*Data[...,1]; result += Data[...,0]. Tek bir formül kullanılmazsa, bu cevap daha doğaldır. - Eric Lebigot


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
2018-03-12 06:47





Bu benim için çalıştı:

giriş:

from scipy import *

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

çıktı:

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

0
2017-07-18 19:08



-1, bu hayali kısım sıfıra eşit bırakır - Pavel Bazant


Performansı gerçekten uzatmak istiyorsanız (büyük dizilerle), numexpr Çok çekirdekten faydalanan kullanılabilir.

Kurmak:

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

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

Hızlı numpy yöntemiyle karşılaştırıldığında:

>>> %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
2017-08-15 12:45