在Numpy / Python中快速稀疏矩阵

时间:2013-03-19 18:47:29

标签: python numpy

我需要(快速)稀疏矩阵。

稀疏 - 将丰度矩阵转换为均匀采样深度。

在此示例中,每行都是一个样本,采样深度是行的总和。我想通过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中有一个功能可以做到这一点,但我不确定它会被称为什么。

2 个答案:

答案 0 :(得分:3)

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

干杯, 的Davide

答案 1 :(得分:1)

我认为问题并不完全清楚。我想稀疏矩阵可以给出从原始矩阵的每个系数中得到的样本数量吗?

查看链接中的代码,可能会加快速度。在转置矩阵上操作并重写链接代码以对列而不是行进行操作。因为这样可以让你的处理器缓存它更好地采样的值,即内存中的跳转更少。

其余的就像我一样,使用numpy(并不一定意味着这是最有效的方式)。

如果你需要它更快,你可以尝试用C ++编写函数代码并用scipy.weave将它包含到你的python中。在C ++中,我会寻找每一行并构建一个位置> 0的查找表,生成min(rowsums(matrix))整数,其范围等于查找表中的项目数。我会累积查找表中每个位置的绘制频率,然后将这些数字放回到数组中的正确位置。该代码应该只是几行。