2010-04-08 66 views
39

Tôi thề là điều này dễ dàng ... Tại sao lại không? :(Numpy: Tạo một mảng phức tạp từ 2 mảng thực?

Trong thực tế, tôi muốn kết hợp 2 phần của mảng tương tự để tạo ra một mảng phức tạp:

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

Những điều này không làm việc:

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

Tôi có thiếu cái gì? Không numpy không thích thực hiện các chức năng mảng trên số phức? Đây là lỗi:

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

Trả lời

50

Điều này dường như làm những gì bạn muốn:

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

Dưới đây là một giải pháp:

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

Và một giải pháp đơn giản hơn:

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

PS: Nếu bạn muốn tiết kiệm bộ nhớ (không mảng trung gian):

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

giải pháp devS 'dưới đây cũng nhanh.

+0

Lỗi tương tự Tôi sợ: TypeError: chỉ mảng dài-1 có thể được chuyển đổi thành Python Scalars –

+0

@Duncan: Tôi đã cập nhật câu trả lời gốc sau khi thực hiện kiểm tra. Nó có vẻ đang hoạt động, bây giờ. – EOL

+0

cảm ơn rất nhiều mà không làm việc. Mặc dù nó rất chậm (như bạn có thể mong đợi - vì nó không thực sự là một chức năng numpy), nó mất 5 giây mỗi vòng lặp bây giờ thay vì 0.1 –

0

đó đã làm việc cho tôi:

đầu vào:

from scipy import * 

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

đầu ra:

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

-1, điều này lá phần tưởng tượng bằng không –

26

Có tất nhiên là khá rõ ràng:

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

Ngoài ra 'Data.view (phức tạp)' –

7

Tôi là người mới làm quen với python vì vậy đây có thể không phải là phương pháp hiệu quả nhất, nhưng nếu tôi hiểu mục đích của câu hỏi một cách chính xác, các bước được liệt kê bên dưới đã hiệu quả với tôi.

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

Ý tưởng thú vị. Tuy nhiên, câu hỏi là về việc kết hợp 'Dữ liệu [:,:,:, 0]' và 'Dữ liệu [:,:,:, 1]' (phức tạp hơn 'a') của bạn. Ngoài ra, thay vì sử dụng 'zeros()', bạn nên sử dụng 'empty()' nhanh hơn và phù hợp hơn. – EOL

+0

Tôi đã so sánh nó với giải pháp Dữ liệu […, 0] + 1j * Dữ liệu […, 1]. Với Data = random.rand (100,100,1000,2), c = số không (a.shape [: - 1], dtype = complex); c.real = Dữ liệu [..., 0]; c.imag = Dữ liệu [..., 1]; nhanh gấp 2 lần Dữ liệu đơn giản […, 0] + 1j * […, 1]. Đáng ngạc nhiên, hiệu quả của việc sử dụng trống thay vì số không là không đáng kể. –

+1

+1. Lưu ý: Tôi nhận được cùng một tốc độ với một biến thể của câu trả lời cuối cùng của tôi: 'result = 1j * Data [..., 1]; kết quả + = Dữ liệu [..., 0] '. Câu trả lời này là tự nhiên hơn, mặc dù, nếu một công thức duy nhất không được sử dụng. – EOL

11

Đây là những gì bạn đang tìm kiếm:

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

Đây chỉ là một phần trùng lặp của các câu trả lời trước đó như Pierre GM hoặc của tôi: Tôi nghĩ rằng hiệu ứng duy nhất của nó là để mất thời gian của mọi người cho hầu như không có giá trị gia tăng (ngoài ví dụ), vì vậy tôi sẽ đề nghị bạn xóa nó. – EOL

14

Nếu phần thực và phần ảo của bạn là những lát dọc theo chiều cuối cùng và mảng của bạn là tiếp giáp dọc theo chiều cuối cùng, bạn chỉ có thể làm

A.view(dtype=np.complex128) 

Nếu bạn đang sử dụng phao nổi đơn chính xác, đây sẽ là

A.view(dtype=np.complex64) 

Dưới đây là một ví dụ đầy đủ hơn

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) 

Nếu bạn muốn thoát khỏi chiều kích bổ sung mà vẫn quanh từ đúc, bạn có thể làm một cái gì đó giống như

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

này hoạt động bởi vì, trong bộ nhớ, một số phức tạp thực sự chỉ là hai số dấu chấm động. Phần đầu tiên đại diện cho phần thực, và phần thứ hai đại diện cho phần ảo. Phương thức xem của mảng thay đổi dtype của mảng để phản ánh rằng bạn muốn xử lý hai giá trị dấu phẩy động liền kề dưới dạng một số phức và cập nhật thứ nguyên tương ứng.

Phương pháp này không sao chép bất kỳ giá trị nào trong mảng hoặc thực hiện bất kỳ phép tính mới nào, tất cả những gì nó tạo ra là một đối tượng mảng mới xem cùng một khối bộ nhớ khác nhau. Điều đó khiến cho hoạt động này có thể được thực hiện nhanh hơn nhiều hơn so với bất kỳ thứ gì có liên quan đến việc sao chép các giá trị. Điều này cũng có nghĩa là mọi thay đổi được thực hiện trong mảng có giá trị phức tạp sẽ được phản ánh trong mảng với các phần thực và tưởng tượng.

Nó cũng có thể là một chút phức tạp hơn để khôi phục mảng ban đầu nếu bạn loại bỏ trục phụ có ngay sau khi loại bỏ. Những thứ như A_comp[...,np.newaxis].view(np.float64) hiện không hoạt động bởi vì, bằng văn bản này, NumPy không phát hiện thấy mảng vẫn là C tiếp giáp khi trục mới được thêm vào. Xem this issue. Tuy nhiên, A_comp.view(np.float64).reshape(A.shape) dường như hoạt động trong hầu hết các trường hợp.

+0

+1: Giải thích rất rõ ràng về những hạn chế của phương pháp. Bạn có thể muốn thêm một giới hạn rõ ràng khác (bộ nhớ chia sẻ giữa 'A_comp' và' A'), và cũng là một lợi thế của phương thức này (tốc độ). – EOL

+0

@EOL Cảm ơn. Tôi đã cập nhật câu trả lời cho phù hợp. – 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) 
Các vấn đề liên quan