web-dev-qa-db-ja.com

mean、nanmeanおよびwarning:空のスライスの平均

私は2つのnumpy配列を構築するとしましょう:

a = np.array([np.NaN, np.NaN])
b = np.array([np.NaN, np.NaN, 3])

これで、np.meannanaの両方に対してbを返すことがわかりました。

>>> np.mean(a)
nan
>>> np.mean(b)
nan

Numpy 1.8(2016年4月20日リリース)以降、 nanmean に恵まれ、nan値を無視します。

>>> np.nanmean(b)
3.0

ただし、配列に何もないbutnan値がある場合、警告が発生します。

>>> np.nanmean(a)
nan
C:\python-3.4.3\lib\site-packages\numpy\lib\nanfunctions.py:598: RuntimeWarning: Mean of empty slice
  warnings.warn("Mean of empty slice", RuntimeWarning)

警告を抑制するのは好きではありません。その警告なしにnanmeanの動作を取得するために使用できるより良い関数はありますか?

50
Michael Currie

警告を抑制するだけの理由はありません。

最も安全な方法は、 warnings.catch_warnings コンテキストマネージャーを使用して、発生が予想される場所でのみ警告を抑制することです。この方法では、一部で予期せず発生する追加のRuntimeWarningsを見逃すことはありませんコードの他の部分:

import numpy as np
import warnings

x = np.ones((1000, 1000)) * np.nan

# I expect to see RuntimeWarnings in this block
with warnings.catch_warnings():
    warnings.simplefilter("ignore", category=RuntimeWarning)
    foo = np.nanmean(x, axis=1)

@dawgのソリューションも機能しますが、最終的に、すべてのNaNの配列でnp.nanmeanの計算を回避するために必要な追加の手順は、警告を抑制するだけで回避できる余分なオーバーヘッドが発生します。また、コードの意図がより明確に反映されます。

49
ali_m

NaN値は、それ自体と等しくないように定義されています。

>>> float('nan') == float('nan')
False
>>> np.NaN == np.NaN
False

Python条件を使用して、nanのプロパティがそれ自体と等しくなることはなく、この動作を取得できます。

>>> a = np.array([np.NaN, np.NaN])
>>> b = np.array([np.NaN, np.NaN, 3])
>>> np.NaN if np.all(a!=a) else np.nanmean(a)
nan
>>> np.NaN if np.all(b!=b) else np.nanmean(b)
3.0

次のこともできます。

import warnings
import numpy as np

a = np.array([np.NaN, np.NaN])
b = np.array([np.NaN, np.NaN, 3])

with warnings.catch_warnings():
    warnings.filterwarnings('error')
    try:
        x=np.nanmean(a)
    except RuntimeWarning:
        x=np.NaN    
print x    
12
dawg