3

平均を計算したいネットワーク内の特定のノードと他のすべてのノードとの間のパス長を含む、多数の 1 次元の numpy ndarray があります。ただし、2 つのノード間にパスが存在しない場合、アルゴリズムはその特定の接続に対して 2147483647 の値を返すため、問題は複雑です。この値をそのままにしておくと、ネットワーク内の典型的なパスの長さが 1 ~ 3 になるため、明らかに平均が大幅に膨らみます。

これに対処する 1 つのオプションは、すべての配列のすべての要素をループして置き換え2147483647、平均を見つけるためNaNに使用numpy.nanmeanすることですが、これはおそらく最も効率的な方法ではありません。のすべての値を無視するだけで平均を計算する方法はあり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

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 に答える