3

我有许多一维 numpy ndarrays,其中包含给定节点和网络中我想计算平均值的所有其他节点之间的路径长度。事情很复杂,因为如果两个节点之间不存在路径,算法会为给定的连接返回 2147483647 的值。如果我不处理这个值,它显然会严重夸大我的平均值,因为我的网络中的典型路径长度将介于 1 到 3 之间。

处理此问题的一种选择是遍历所有数组的所有元素并替换2147483647NaN然后使用numpy.nanmean来查找平均值,尽管这可能不是最有效的方法。有没有办法用 numpy 计算平均值而忽略 的所有值2147483647

我应该补充一点,我可以有多达几百万个数组和几百万个值来平均,因此在如何找到平均值方面的任何性能提升都会产生真正的影响。

4

3 回答 3

5

为什么不使用通常的 numpy 过滤呢?

m = my_array[my_array != 2147483647].mean()

顺便说一句,如果你真的想要速度,你的整个算法描述看起来肯定很幼稚,可以改进很多。

哦,我猜您正在计算平均值,因为您已经严格检查了基础分布是否正常,因此它意味着什么,不是吗?

于 2016-08-24T16:09:12.870 回答
1
np.nanmean(np.where(my_array == 2147483647, np.nan, my_array))

计时

a = np.random.randn(100000)
a[::10] = 2147483647

%timeit np.nanmean(np.where(a == 2147483647, np.nan, a))
1000 loops, best of 3: 639 µs per loop

%timeit a[a != 2147483647].mean()
1000 loops, best of 3: 259 µs per loop

import pandas as pd

%timeit pd.Series(a).ne(2147483647).mean()
1000 loops, best of 3: 493 µs per loop
于 2016-08-24T16:13:58.000 回答
1

一种方法是一次性获得所有元素的总和,然后从无效元素中移除贡献。最后,我们需要得到平均值本身,除以有效元素的数量。所以,我们会有一个像这样的实现 -

def mean_ignore_num(arr,num):
    # Get count of invalid ones
    invc = np.count_nonzero(arr==num)

    # Get the average value for all numbers and remove contribution from num
    return (arr.sum() - invc*num)/float(arr.size-invc)

验证结果 -

In [191]: arr = np.full(10,2147483647).astype(np.int32)
     ...: arr[1] = 5
     ...: arr[4] = 4
     ...: 

In [192]: arr.max()
Out[192]: 2147483647

In [193]: arr.sum() # Extends beyond int32 max limit, so no overflow
Out[193]: 17179869185

In [194]: arr[arr != 2147483647].mean()
Out[194]: 4.5

In [195]: mean_ignore_num(arr,2147483647)
Out[195]: 4.5

运行时测试 -

In [38]: arr = np.random.randint(0,9,(10000))

In [39]: arr[arr != 7].mean()
Out[39]: 3.6704609489462414

In [40]: mean_ignore_num(arr,7)
Out[40]: 3.6704609489462414

In [41]: %timeit arr[arr != 7].mean()
10000 loops, best of 3: 102 µs per loop

In [42]: %timeit mean_ignore_num(arr,7)
10000 loops, best of 3: 36.6 µs per loop
于 2016-08-24T16:54:58.927 回答