2014-04-09 41 views
5

隨機選擇,我有一個名爲ARR具有N值的巨大np.array,並通過隨機選擇這些值的10%:反轉鍵在numpy的陣列

choice=random.sample(range(N), int(N*percent)) # percent has values 0-1 
newarr=arr[choice] 

n可以取爲超過200萬的值。

其實我也需要一個數組與其他90%的值。所以目前我使用以下非常慢的:

def buildRevChoice(choice, nevents): 
     revChoice=[] 
     for i in range(N): 
      if not i in choice: 
       revChoice.append(i) 
     return revChoice 

你能想出一種方法來解決這個問題嗎?

+0

快速優化:在'buildRevChoice'中,從'choice'創建一個'set'來加速查找。 –

+1

如果你需要性能的話,根本不要對python循環使用大數組。使用python/numpy和numpy矢量化的函數式編程。 –

+0

是的,我知道,但我沒有發現每個谷歌的另一個解決方案。無法想到一個合理的搜索短語。 – user575736

回答

6

你可以只需random.shuffle的清單,然後按你喜歡的方式拆分它。

def choice(N, percent): 
    tmp = range(N) 
    random.shuffle(tmp) 
    cut = int(N * percent) 
    return tmp[:cut], tmp[cut:] 

,你會得到你的兩個列表,第一個包含了選民和含有剩餘部分的第二。

+2

不是一個不好的解決方案;儘管我對random.shuffle的性能有點警惕。潛在地,random.permutation有更好的表現。取決於如何實現,np.argsort(random.randint())可能是更快的方法來生成置換索引。 –

+0

@EelcoHoogendoorn我沒有使用'numpy',所以我知道的只是基本的Python :)請問O(n)Fisher Yates Shuffle算法是洗牌的好選擇嗎? – 0605002

+0

你自己實現的任何算法都是不好的選擇,除非你打算編寫一個C擴展。請注意,我喜歡基準洗牌;我只是想象最隨機的就地洗牌算法不一定是最有效的。 –

2

如果可以使用掩碼數組的內存開銷,這似乎比按索引選擇其他值更快,並保留are中元素的順序。以下是我與時序得到了IPython的筆記本:

N = 2000000 
arr = random.random(N) 
percent = 0.10 

我的解決辦法:

%% timeit 
choice = random.choice(N, N*percent) 
mask = zeros_like(arr, bool) 
mask[choice] = True 
newarr = arr[mask] 
revchoice = arr[~mask] 

10圈,最好的3:每圈18.1毫秒

0605002的解決方案:

tmp = range(N) 
random.shuffle(tmp) 
cut = int(N * percent) 
newarr, revchoice = tmp[:cut], tmp[cut:] 

1個迴路,最好3個:每個迴路603 ms

+0

非常感謝,這是兩個非常好的解決方案,我會檢查哪一個更快。我不習慣記憶問題。在這種情況下,我不應該使用口罩? – user575736

+1

這個解決方案(和另一個0605002)使用與'arr'具有相同大小的數組。所以如果你的陣列只有可用內存的一半大小,你將沒有足夠的空間來創建掩碼。如果避免構建掩碼,那麼索引數組的內存可能會多出10%。不過,200萬分並不是那麼多。 – chthonicdaemon

+1

我已經用時機更新了我的答案。我的解決方案速度要快一個數量級。 – chthonicdaemon