2013-03-19 258 views
2

我需要(快速)稀疏矩陣。在Numpy/Python中快速稀疏矩陣

稀疏 - 將丰度矩陣轉換爲均勻的採樣深度。

在這個例子中,每行是一個樣本,採樣深度是行的總和。我想通過min(rowsums(matrix))樣本隨機抽樣(替換)矩陣。

假設我有一個矩陣:

>>> m = [ [0, 9, 0], 
...  [0, 3, 3], 
...  [0, 4, 4] ] 

稀疏功能由行進行與替換隨機抽樣min(rowsums(matrix))倍(這是6在這種情況下)。

>>> rf = rarefaction(m) 
>>> rf 
    [ [0, 6, 0], # sum = 6 
     [0, 3, 3], # sum = 6 
     [0, 3, 3] ] # sum = 6 

結果是隨機的,但行數總是相同的。

>>> rf = rarefaction(m) 
>>> rf 
    [ [0, 6, 0], # sum = 6 
     [0, 2, 4], # sum = 6 
     [0, 4, 2], ] # sum = 6 

PyCogent有做這個逐行但它是在大型矩陣非常緩慢的功能。

我有一種感覺,在Numpy中有一個功能可以做到這一點,但我不知道它會被稱爲。

+0

我想'nowsums'真正的意思'rowsums'? – 2013-03-19 19:23:11

+0

是的,謝謝。 – 2013-03-19 19:30:20

回答

2
import numpy as np 
from numpy.random import RandomState 

def rarefaction(M, seed=0): 
    prng = RandomState(seed) # reproducible results 
    noccur = np.sum(M, axis=1) # number of occurrences for each sample 
    nvar = M.shape[1] # number of variables 
    depth = np.min(noccur) # sampling depth 

    Mrarefied = np.empty_like(M) 
    for i in range(M.shape[0]): # for each sample 
     p = M[i]/float(noccur[i]) # relative frequency/probability 
     choice = prng.choice(nvar, depth, p=p) 
     Mrarefied[i] = np.bincount(choice, minlength=nvar) 

    return Mrarefied 

例子:

>>> M = np.array([[0, 9, 0], [0, 3, 3], [0, 4, 4]]) 
>>> M 
array([[0, 9, 0], 
     [0, 3, 3], 
     [0, 4, 4]]) 
>>> rarefaction(M) 
array([[0, 6, 0], 
     [0, 2, 4], 
     [0, 3, 3]]) 
>>> rarefaction(M, seed=1) 
array([[0, 6, 0], 
     [0, 4, 2], 
     [0, 3, 3]]) 
>>> rarefaction(M, seed=2) 
array([[0, 6, 0], 
     [0, 3, 3], 
     [0, 3, 3]]) 

乾杯, 達維德

1

我覺得這個問題並不完全清楚。我想這個稀疏矩陣給你從原始矩陣的每個係數中取出的樣本數量?

查看鏈接中的代碼,可能會加快速度。在轉置的矩陣上操作並重寫鏈接的代碼以在列上而不是在行上操作。因爲這樣可以讓你的處理器緩存它採樣得更好的值,也就是說內存中的跳轉較少。

其餘的就像我會這樣做,使用numpy(並不一定意味着這是最有效的方式)。

如果你需要它更快,你可以嘗試在C++中編寫函數,並用scipy.weave將它包含到你的python中。在C++中,我會去每一行,並建立一個> 0的位置查找表,在與查找表中的項目數相等的範圍內生成整數。我會累積查找表中每個位置的繪製頻率,然後將這些數字放回到數組中的正確位置。該代碼應該只是簡單的幾行。