2014-10-11 21 views
6

Tôi có một mảng 2 chiều các số nguyên, chúng tôi sẽ gọi nó là "A".nhanh chóng tính toán mảng numpy 3D ngẫu nhiên từ mảng numpy 2D

Tôi muốn tạo ra một mảng 3 chiều "B" của tất cả các 1s và 0s đến nỗi:

  • cho bất kỳ cố định (i, j) sum(B[i,j,:])==A[i.j], có nghĩa là, B[i,j,:] chứa A[i,j]1s trong đó
  • số 1 được đặt ngẫu nhiên trong thứ nguyên thứ 3.

Tôi biết cách tôi sẽ làm điều này bằng cách sử dụng chỉ mục chuẩn python nhưng điều này hóa ra rất chậm.

Tôi đang tìm cách để thực hiện việc này, tận dụng các tính năng có thể khiến Numpy nhanh.

Dưới đây là làm thế nào tôi sẽ làm điều đó bằng lập chỉ mục tiêu chuẩn:

B=np.zeros((X,Y,Z)) 
indexoptions=range(Z) 

for i in xrange(Y): 
    for j in xrange(X): 
     replacedindices=np.random.choice(indexoptions,size=A[i,j],replace=False) 
     B[i,j,[replacedindices]]=1 

Ai đó có thể vui lòng giải thích làm thế nào tôi có thể làm điều này một cách nhanh hơn?

Edit: Đây là một ví dụ "A":

A=np.array([[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4]]) 

trong trường hợp này X = Y = 5 và Z> = 5

+1

Đang cố gắng thực hiện tiến trình này, tôi đã hỏi một câu hỏi đơn giản hơn: http://stackoverflow.com/questions/26310897/numpy-create-bool-array-like-repeat-but-in-multiple-dimensions - nhưng sau đó tôi nhận ra rằng 'np.random.shuffle (np.rollaxis (B, 2)) đã được lên kế hoạch của tôi' không xáo trộn tất cả các hàng một cách độc lập, vì vậy đây chưa hẳn là câu trả lời. Khối xây dựng, có thể. :) –

Trả lời

4

Về cơ bản những ý tưởng tương tự như @JohnZwinck và @DSM, nhưng với một chức năng shuffle cho xáo trộn một trục đưa ra:

import numpy as np 

def shuffle(a, axis=-1): 
    """ 
    Shuffle `a` in-place along the given axis. 

    Apply numpy.random.shuffle to the given axis of `a`. 
    Each one-dimensional slice is shuffled independently. 
    """ 
    b = a.swapaxes(axis,-1) 
    # Shuffle `b` in-place along the last axis. `b` is a view of `a`, 
    # so `a` is shuffled in place, too. 
    shp = b.shape[:-1] 
    for ndx in np.ndindex(shp): 
     np.random.shuffle(b[ndx]) 
    return 


def random_bits(a, n): 
    b = (a[..., np.newaxis] > np.arange(n)).astype(int) 
    shuffle(b) 
    return b 


if __name__ == "__main__": 
    np.random.seed(12345) 

    A = np.random.randint(0, 5, size=(3,4)) 
    Z = 6 

    B = random_bits(A, Z) 

    print "A:" 
    print A 
    print "B:" 
    print B 

Output:

A: 
[[2 1 4 1] 
[2 1 1 3] 
[1 3 0 2]] 
B: 
[[[1 0 0 0 0 1] 
    [0 1 0 0 0 0] 
    [0 1 1 1 1 0] 
    [0 0 0 1 0 0]] 

[[0 1 0 1 0 0] 
    [0 0 0 1 0 0] 
    [0 0 1 0 0 0] 
    [1 0 1 0 1 0]] 

[[0 0 0 0 0 1] 
    [0 0 1 1 1 0] 
    [0 0 0 0 0 0] 
    [0 0 1 0 1 0]]] 
+0

Hmmph. Tôi bực mình rằng 'shuffle' không hoạt động như tôi nghĩ. Có thể tránh được vòng lặp cấp Python bằng cách định hình lại đối tượng D thấp hơn và xáo trộn không? – DSM

+1

@DSM: Tôi chia sẻ sự khó chịu của bạn! Tôi không thể tìm ra cách để thực hiện công việc này chỉ với một cuộc gọi đến 'np.random.shuffle'. (Phiên bản đầu tiên của tôi là 'shuffle' - không được hiển thị ở đây - là một thuật toán Fisher-Yates được vector hóa, nhưng nó không rõ ràng như thuật toán này, và có lẽ chậm hơn rất nhiều khi kích thước không trục này nhỏ.) –

+0

Cảm ơn! Đối với mảng lớn, phương pháp này nhanh hơn 100 lần so với cách tôi làm ban đầu. – nickexists

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