2013-06-15 38 views
6

Tôi muốn ánh xạ một numpy.array từ NxM để NxMx3, nơi một vector của ba yếu tố là một chức năng của sự xâm nhập ban đầu:Mapping yếu tố khôn ngoan một mảng NumPy vào một mảng nhiều chiều

lambda x: [f1(x), f2(x), f3(x)] 

Tuy nhiên, mọi thứ như numpy.vectorize không cho phép thay đổi kích thước. Chắc chắn, tôi có thể tạo một dãy số không và tạo một vòng lặp (and it is what I am doing by now), nhưng nó không âm thanh không phải là Pythonic cũng không hiệu quả (như mọi vòng lặp trong Python).

Có cách nào tốt hơn để thực hiện thao tác theo nguyên tố trên numpy.array, tạo ra vec-tơ cho mỗi mục nhập không?

+0

Nếu 'N' và' M' lớn hơn đáng kể so với 3, vòng lặp trên thứ nguyên thứ ba sẽ có ảnh hưởng không đáng kể đến hiệu suất. Và không có gì không phải là pythonic trong việc sử dụng cho các vòng lặp! Những gì không phải là rất numpythonic hoặc hiệu quả là sử dụng 'np.vectorize'. Bạn có thể thử chuyển đổi 'f1',' f2' và 'f3' thành một hàm duy nhất lấy mảng và mảng trả về. Không biết chức năng của bạn đang làm gì, bạn không thể biết liệu phương pháp này có phù hợp với vấn đề của bạn hay không. – Jaime

+0

@Jaime Tôi đang lặp qua N và M, không phải 3. Vấn đề là chuyển đổi các số phức trong ba phao [R, G, B], vì vậy tôi có thể vẽ một hàm phức tạp (xem liên kết trong câu hỏi). –

Trả lời

3

Bây giờ mà tôi nhìn thấy mã của bạn, cho các hoạt động toán học đơn giản nhất bạn có thể cho numpy làm vòng lặp, những gì thường được gọi là vectơ hóa:

def complex_array_to_rgb(X, theme='dark', rmax=None): 
    '''Takes an array of complex number and converts it to an array of [r, g, b], 
    where phase gives hue and saturaton/value are given by the absolute value. 
    Especially for use with imshow for complex plots.''' 
    absmax = rmax or np.abs(X).max() 
    Y = np.zeros(X.shape + (3,), dtype='float') 
    Y[..., 0] = np.angle(X)/(2 * pi) % 1 
    if theme == 'light': 
     Y[..., 1] = np.clip(np.abs(X)/absmax, 0, 1) 
     Y[..., 2] = 1 
    elif theme == 'dark': 
     Y[..., 1] = 1 
     Y[..., 2] = np.clip(np.abs(X)/absmax, 0, 1) 
    Y = matplotlib.colors.hsv_to_rgb(Y) 
    return Y 

Mã này sẽ chạy nhanh hơn nhiều so với mã của bạn.

+0

Tôi không biết rằng có thể tham khảo các ma trận con là 'Y [..., i]' hoặc 'Y [i, ...]'. Cảm ơn! Có một tên cụ thể cho hoạt động này không? (Tôi đã googling * vectorization *, nhưng nó trả về những thứ như 'np.vectorize'.) –

+1

Đó là ký hiệu _ellipsis_. Sửa lỗi đánh máy. – Jaime

+0

Tôi hiểu. Bây giờ tôi thấy một số ghi chú về nó: http://stackoverflow.com/a/773472/907575 và http://stackoverflow.com/questions/118370/how-do-you-use-the-ellipsis-slicing-syntax- trong python. –

4

Nếu tôi hiểu vấn đề của bạn một cách chính xác, tôi đề nghị bạn sử dụng np.dstack:

Docstring: 
Stack arrays in sequence depth wise (along third axis). 

Takes a sequence of arrays and stack them along the third axis 
to make a single array. Rebuilds arrays divided by `dsplit`. 
This is a simple way to stack 2D arrays (images) into a single 
3D array for processing. 

In [1]: a = np.arange(9).reshape(3, 3) 

    In [2]: a 
    Out[2]: 
    array([[0, 1, 2], 
      [3, 4, 5], 
      [6, 7, 8]]) 

    In [3]: x, y, z = a*1, a*2, a*3 # in your case f1(a), f2(a), f3(a) 

    In [4]: np.dstack((x, y, z)) 
    Out[4]: 
    array([[[ 0, 0, 0], 
      [ 1, 2, 3], 
      [ 2, 4, 6]], 

      [[ 3, 6, 9], 
      [ 4, 8, 12], 
      [ 5, 10, 15]], 

      [[ 6, 12, 18], 
      [ 7, 14, 21], 
      [ 8, 16, 24]]]) 
+0

Tôi sẽ tránh định nghĩa 'x, y, z' trước để lưu bộ nhớ, gọi các hàm bên trong' np.dstack() ' –

+0

@sgpc - Bạn nói đúng. Tôi chỉ làm điều đó cho rõ ràng hơn. – root

+0

+1 Đẹp và hoạt động. Tôi chấp nhận câu trả lời của Jaime vì nó thuận tiện hơn cho mục đích của tôi và cho một số khái quát. –

Các vấn đề liên quan