Python中带有NaN值的数组的平均值

4

我在Python中有三个数组

a = np.array([[10., 10., 10., 10.], [10., nan, 10., 10.], [10., 10., nan, 10.]])
b = np.array([[10., 10., 10., 10.], [10., 10., 10., nan], [10., 10.,nan, 10]])
c = np.array([[10., nan, 10., 10.], [nan, 10., 10., nan], [10., 10.,nan, 10]])

我需要计算平均值才能得到以下数组:

>>> myavg 
array([[ 10.,  10,  10.,  10.],
       [ 10,  10.,  10.,  10.],
       [ 10.,  10.,  nan,  10.]])

第一步是将数组转换为新的[0,1]数组并求和(即3 = 每个数组中的数据,2 = 仅在两个数组中的数据,1 = 仅在一个数组中的数据,0 = 没有数据)

aa = a.copy()
bb = b.copy()
cc = c.copy()
aa[aa == 10.] = 1
aa[aa != 1] = 0
bb[bb == 10.] = 1
bb[bb != 1] = 0
cc[cc == 10.] = 1
cc[cc != 1] = 0
dd = aa + bb + cc

>>> dd
array([[ 3.,  2.,  3.,  3.],
       [ 2.,  2.,  3.,  1.],
       [ 3.,  3.,  0.,  3.]])

第二个步骤是将原始数组中的所有数字相加,然后除以dd。
c = a+b+c
>>> c
array([[ 30.,  nan,  30.,  30.],
       [ nan,  nan,  30.,  nan],
       [ 30.,  30.,  nan,  30.]])

问题非常明显。当我将一个值与NaN相加时,会得到NaN。我不能将NaN转换为“0”,因为在我的实际情况中,“0”是一个值(例如温度)。
3个回答

5

您可以将abc放入一个三维数组中,然后使用numpy.nanmean

In [2]: %paste
a = np.array([[10., 10., 10., 10.], [10., nan, 10., 10.], [10., 10., nan, 10.]])
b = np.array([[10., 10., 10., 10.], [10., 10., 10., nan], [10., 10.,nan, 10]])
c = np.array([[10., nan, 10., 10.], [nan, 10., 10., nan], [10., 10.,nan, 10]])

## -- End pasted text --

In [3]: m = np.array([a, b, c])

In [4]: np.nanmean(m, axis=0)
/Users/warren/anaconda/lib/python2.7/site-packages/numpy/lib/nanfunctions.py:675: RuntimeWarning: Mean of empty slice
  warnings.warn("Mean of empty slice", RuntimeWarning)
Out[4]: 
array([[ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  nan,  10.]])

警告出现的原因是,在某些情况下被平均的所有值都是NaN。

1
简单来说,在计算dd之后,但在计算c之前,将NaN设置为零即可。这样,在c中将忽略NaN,并得到所需的平均值。
将NaN设置为零的简单方法是:http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.nan_to_num.html 然而,还有一个问题,即您的dd矩阵在索引[2,2]处为零。为了解决这个问题,只需将其设置为NaN(因为如果dd条目为零,则我们可以忽略此平均值/此索引没有平均值)。
以下是可行的代码:
import numpy as np
from numpy import nan

a = np.array([[10., 10., 10., 10.], [10., nan, 10., 10.], [10., 10., nan, 10.]])
b = np.array([[10., 10., 10., 10.], [10., 10., 10., nan], [10., 10.,nan, 10]])
c = np.array([[10., nan, 10., 10.], [nan, 10., 10., nan], [10., 10.,nan, 10]])

aa = a.copy()
bb = b.copy()
cc = c.copy()
aa[aa == 10.] = 1
aa[aa != 1] = 0
bb[bb == 10.] = 1
bb[bb != 1] = 0
cc[cc == 10.] = 1
cc[cc != 1] = 0
dd = aa + bb + cc
dd[dd == 0] = nan

c = np.nan_to_num(a) + np.nan_to_num(b) + np.nan_to_num(c)

your_avg = c / dd

$your_avg
array([[ 10.,  10.,  10.,  10.],
   [ 10.,  10.,  10.,  10.],
   [ 10.,  10.,  nan,  10.]])

一条额外的建议。如果您可以将数据重新格式化为每个包含三个条目的12个数组,则可以使用:http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.nanmean.html 或者如Warren所建议的那样,将其放入单个3D数组中。这非常巧妙!

0
这将是一个很好的使用掩码数组的例子。
将这三个合并成一个数组(3D):
In [257]: abc=np.array([a,b,c])

你需要的是第一个轴上的平均值,但要注意nan会传播。

In [258]: abc.mean(axis=0)
Out[258]: 
array([[ 10.,  nan,  10.,  10.],
       [ nan,  nan,  10.,  nan],
       [ 10.,  10.,  nan,  10.]])

创建一个掩蔽数组,将nan掩盖掉:
In [259]: abcm=np.ma.masked_where(np.isnan(abc),abc)

In [260]: abcm
Out[260]: 
masked_array(data =
 [[[10.0 10.0 10.0 10.0]
  [10.0 -- 10.0 10.0]
  [10.0 10.0 -- 10.0]]

 [[10.0 10.0 10.0 10.0]
  [10.0 10.0 10.0 --]
  [10.0 10.0 -- 10.0]]

 [[10.0 -- 10.0 10.0]
  [-- 10.0 10.0 --]
  [10.0 10.0 -- 10.0]]],
             mask =
 [[[False False False False]
  [False  True False False]
  [False False  True False]]

 [[False False False False]
  [False False False  True]
  [False False  True False]]

 [[False  True False False]
  [ True False False  True]
  [False False  True False]]],
       fill_value = 1e+20)

现在我可以计算平均值,而不会受到NaN的影响 - 除了所有值都是NaN的单元格。
In [261]: abcm.mean(axis=0)
Out[261]: 
masked_array(data =
 [[10.0 10.0 10.0 10.0]
 [10.0 10.0 10.0 10.0]
 [10.0 10.0 -- 10.0]],
             mask =
 [[False False False False]
 [False False False False]
 [False False  True False]],
       fill_value = 1e+20)

并将其转换回带有filled的常规数组:

In [262]: abcm.mean(axis=0).filled(np.nan)
Out[262]: 
array([[ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  nan,  10.]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接