`numpy.nanpercentile`非常慢

时间:2020-02-01 08:31:53

标签: python numpy cupy

numpy.nanpercentile非常慢。 因此,我想使用cupy.nanpercentile;但尚未实施cupy.nanpercentile。 有人有解决方案吗?

2 个答案:

答案 0 :(得分:1)

我也遇到了 np.nanpercentile 对于我的数据集非常慢的问题。我找到了一个 wokraround,可以让你使用标准的 np.percentile。它也可以应用于许多其他库。

这个应该可以解决你的问题。而且它的运行速度也比 np.nanpercentile 快很多:

arr = np.array([[np.nan,2,3,1,2,3],
                [np.nan,np.nan,1,3,2,1],
                [4,5,6,7,np.nan,9]])

mask = (arr >= np.nanmin(arr)).astype(int)

count = mask.sum(axis=1)
groups = np.unique(count)
groups = groups[groups > 0]

p90 = np.zeros((arr.shape[0]))
for g in range(len(groups)):
    pos = np.where (count == groups[g])
    values = arr[pos]
    values = np.nan_to_num (values, nan=(np.nanmin(arr)-1))
    values = np.sort (values, axis=1)
    values = values[:,-groups[g]:]
    p90[pos] = np.percentile (values, 90, axis=1)

因此,它不是用 nans 取百分位数,而是按有效数据量对行进行排序,并取这些行的百分位数分开。然后将所有内容重新添加在一起。这也适用于 3D 数组,只需添加 y_pos 和 x_pos 而不是 pos。并注意您正在计算的轴。

答案 1 :(得分:0)

def testset_gen(num):
    init=[]
    for i in range (num):
        a=random.randint(65,122) # Dummy name
        b=random.randint(1,100) # Dummy value: 11~100 and 10% of nan
        if b<11:
            b=np.nan # 10% = nan
        init.append([a,b])
    return np.array(init)

np_testset = testset_gen(30000000)#468,751KB

def f1_np (arr, num):
    return np.percentile (arr[:,1], num)
# 55.0, 0.523902416229248 sec

打印(f1_np(np_testset [:,1],50))

def cupy_nanpercentile (arr, num):
    return len(cp.where(arr > num)[0]) / (len(arr) - cp.sum(cp.isnan(arr))) * 100
    # 55.548758317136446, 0.3640251159667969 sec
    # 43% faster
    # If You need same result, use int(). But You lose saved time.

打印(cupy_nanpercentile(cp_testset [:,1],50))

我无法想象测试结果需要几天的时间。使用我的计算机,似乎有1万亿行数据或更多。因此,由于资源不足,我无法重现同样的问题。