简短问题
我有一个很大的10000x10000个元素的图像,我把它放在几百个不同的扇区/框中。然后,我需要对每个bin中包含的值执行一些迭代计算。
如何提取每个bin的索引,以便使用bins值有效地执行计算?
我正在寻找的是一种解决方案,它可以避免每次都要从我的大型数组中选择ind == j
的瓶颈。有没有一种方法可以一次性直接获得属于每个bin的元素的索引?
详细说明
1.简单的解决方案
实现我所需的一种方法是使用如下代码(参见THIS相关答案),其中我将我的值数字化,然后使用j循环选择等于j的数字化索引,如下所示
import numpy as np
# This function func() is just a placemark for a much more complicated function.
# I am aware that my problem could be easily sped up in the specific case of
# of the sum() function, but I am looking for a general solution to the problem.
def func(x):
y = np.sum(x)
return y
vals = np.random.random(1e8)
nbins = 100
bins = np.linspace(0, 1, nbins+1)
ind = np.digitize(vals, bins)
result = [func(vals[ind == j]) for j in range(1, nbins)]
这不是我想要的,因为它每次都从我的大型数组中选择ind == j
。这使得这个解决方案非常低效和缓慢。
2.使用binned_statistics
对于用户定义函数的一般情况,上述方法与在scipy.stats.binned_statistic中实现的方法相同。直接使用Scipy可以获得相同的输出,如下所示
import numpy as np
from scipy.stats import binned_statistics
vals = np.random.random(1e8)
results = binned_statistic(vals, vals, statistic=func, bins=100, range=[0, 1])[0]
3.使用labeled_comprehension
另一种Scipy替代方案是使用scipy.ndimage.measurements.labeled_comprehension。使用该函数,上面的示例将变成
import numpy as np
from scipy.ndimage import labeled_comprehension
vals = np.random.random(1e8)
nbins = 100
bins = np.linspace(0, 1, nbins+1)
ind = np.digitize(vals, bins)
result = labeled_comprehension(vals, ind, np.arange(1, nbins), func, float, 0)
不幸的是,这种形式的效率也很低,尤其是与我的原始示例相比,它没有速度优势。
4.与IDL语言的比较
为了进一步澄清,我正在寻找的功能相当于IDL语言HERE的HISTOGRAM
函数中的REVERSE_INDICES
关键字。这个非常有用的功能可以在Python中高效地复制吗?
具体地说,使用IDL语言,上面的例子可以写成
vals = randomu(s, 1e8)
nbins = 100
bins = [0:1:1./nbins]
h = histogram(vals, MIN=bins[0], MAX=bins[-2], NBINS=nbins, REVERSE_INDICES=r)
result = dblarr(nbins)
for j=0, nbins-1 do begin
jbins = r[r[j]:r[j+1]-1] ; Selects indices of bin j
result[j] = func(vals[jbins])
endfor
上面的IDL实现比Numpy实现快大约10倍,这是因为不必为每个bin选择bin的索引。并且支持IDL实现的速度差异随着箱的数量的增加而增加。
https://stackoverflow.com/questions/26783719
复制相似问题