1. ホーム
  2. python

[解決済み] NumPyでNaNを高速にチェックする

2022-05-24 01:26:53

質問

NaNの発生を確認する最も速い方法を探しています ( np.nan ) をチェックする最速の方法を探しています。 X . np.isnan(X) は論外として、形状のブーリアン配列を構築するので X.shape という形のブール型配列を構築するため、これは巨大になる可能性があるからです。

私は np.nan in X を試してみましたが、これはうまくいかないようです。 np.nan != np.nan . 高速でメモリ効率の良い方法は全くないのでしょうか?

("どのように巨大なのか"と尋ねるであろう人々へ。私にはわかりません。これはライブラリ コードの入力検証です)。

どのように解決するのですか?

Rayの解決策は良いものです。しかし、私のマシンでは、2.5 倍ほど速く numpy.sum の代わりに numpy.min :

In [13]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 244 us per loop

In [14]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 97.3 us per loop

とは異なり min , sum は分岐を必要としないので、最近のハードウェアではかなり高価になる傾向があります。これはおそらく sum の方が速い理由です。

編集 上記のテストは、配列のちょうど真ん中あたりにNaNが1つある状態で行われました。

興味深いのは min はNaNがない場合よりもNaNがある場合の方が遅いことに注意してください。また、NaNが配列の先頭に近いほど遅くなるようです。一方 sum のスループットは、NaNがあるかどうか、どこにあるかには関係なく一定のようです。

In [40]: x = np.random.rand(100000)

In [41]: %timeit np.isnan(np.min(x))
10000 loops, best of 3: 153 us per loop

In [42]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop

In [43]: x[50000] = np.nan

In [44]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 239 us per loop

In [45]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.8 us per loop

In [46]: x[0] = np.nan

In [47]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 326 us per loop

In [48]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop