访问 Python 中的大量未排序数组元素

Accessing a large number of unsorted array elements in Python

我在Python方面不是很熟练。但是,我对 R 非常得心应手。然而,我确实必须使用 Python,因为它具有与 Cplex 的最新接口。我还试图避免在 C/C++

中必须进行的所有额外编码

也就是说,我在大型 lists/arrays/matrices...

上遇到速度和效率问题

我很快用 R 写了两行,虽然很丑,但效果还不错...

doses = sapply(organSets[[2]], function(x) sum(voxMap_beamlet_val[which(voxMap_beamlet_iInd[,1] == x),1]))
length(which(doses <= sum(doses)/length(organSets[[2]])))/length(doses)

...这些行在 length(organSets[[2]])=52960length(voxMap_beamlet_val) = length(voxMap_beamlet_iInd) = 1217077

的大约 5 分钟内执行

然而,在Python,类似的事情需要大约两个小时。通过使用 scipy.sparse,执行时间减少了一半,大约一个小时......这显然仍然是不可接受的......

Python代码如下...

voxMapBeamlet = sparse.coo_matrix((voxMap_beamlet_val,(voxMap_beamlet_iInd,voxMap_beamlet_jInd)),shape=(1055736,8500))
def getDose(voxInd):
    return sum([x.sum() for x in voxMapBeamlet.getrow(voxInd)])

def probDoseLevel2(orgVox,level=None):
    voxDose2 = [0] * len(orgVox)
    for i,v in enumerate(orgVox):
        voxDose2[i] = getDose(v)
    if level == None:
        level = sum(voxDose2)/len(orgVox)
    print len([x for x in voxDose2 if x <= level])/len(orgVox)

probDoseLevel2(organSets[1])

请指教

首先,您需要高效地访问行,而 COO 格式无法做到这一点。将您的 voxMapBeamlet 转换为压缩稀疏行格式,getrow 变得更加高效:

voxMapBeamlet = sparse.coo_matrix((voxMap_beamlet_val,(voxMap_beamlet_iInd,voxMap_beamlet_jInd)),shape=(1055736,8500))
voxMapBeamlet = voxMapBeamlet.tocsr()

其次,getDose比需要的复杂得多:

def getDose(voxInd):
    return voxMapBeamlet.getrow(voxInd).sum()

我怀疑这已经足够快了,但我们应该能够进一步推动它。我们可以使用广播和高级索引将更多工作从 Python 字节码中推送到 C 级例程中:

def probDoseLevel2(orgVox,level=None):
    relevantRows = voxMapBeamlet[orgVox]

    # Dense column matrix of row sums
    voxDose2 = relevantRows.sum(axis=1)
    if level is None:
        level = voxDose2.sum()/len(orgVox)
    return (voxDose2 <= level).sum() / len(orgVox)

最后,如果您使用的是 Python 2,则最后一行中的除法是整数除法。这将始终在这里产生 0 或 1,因为 len(orgVox) 至少与分子一样大。生成 level 的除法可能存在类似的问题,具体取决于您正在使用的数据的数据类型。要打开真正的分裂,你可以把

from __future__ import division

在文件的顶部。