非零值的 Numpy 平均值
Numpy mean of nonzero values
我有一个大小为 N*M 的矩阵,我想求出每一行的平均值。值从 1 到 5,没有任何值的条目设置为 0。但是,当我想使用以下方法找到平均值时,它给了我错误的平均值,因为它还计算了值为0.
matrix_row_mean= matrix.mean(axis=1)
我怎样才能得到非零值的平均值?
获取每行中非零的计数,并将其用于计算每行求和的平均值。因此,实现看起来像这样 -
np.true_divide(matrix.sum(1),(matrix!=0).sum(1))
如果你使用的是旧版本的 NumPy,你可以使用计数的浮点数转换来替换 np.true_divide
,就像这样 -
matrix.sum(1)/(matrix!=0).sum(1).astype(float)
样本运行-
In [160]: matrix
Out[160]:
array([[0, 0, 1, 0, 2],
[1, 0, 0, 2, 0],
[0, 1, 1, 0, 0],
[0, 2, 2, 2, 2]])
In [161]: np.true_divide(matrix.sum(1),(matrix!=0).sum(1))
Out[161]: array([ 1.5, 1.5, 1. , 2. ])
另一种解决问题的方法是用 NaNs
替换零,然后使用 np.nanmean
,这将忽略那些 NaNs
,实际上那些原始的 zeros
, 像这样 -
np.nanmean(np.where(matrix!=0,matrix,np.nan),1)
从性能的角度来看,我会推荐第一种方法。
我将在这里详细说明使用 masked array 的更通用的解决方案。为了说明细节,让我们创建一个只有一个的下三角矩阵:
matrix = np.tril(np.ones((5, 5)), 0)
如果您对上面的术语不清楚,则此矩阵如下所示:
[[ 1., 0., 0., 0., 0.],
[ 1., 1., 0., 0., 0.],
[ 1., 1., 1., 0., 0.],
[ 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1.]]
现在,我们希望我们的函数 return 每行的平均值为 1。或者换句话说,轴 1 上的平均值等于五个 1 的向量。为了实现这一点,我们创建了一个屏蔽矩阵 ,其中值为零的条目被视为无效 。这可以通过 np.ma.masked_equal
:
来实现
masked = np.ma.masked_equal(matrix, 0)
最后,我们在此数组中执行 numpy 操作,系统地忽略被屏蔽的元素(0)。考虑到这一点,我们通过以下方式获得所需的结果:
masked.mean(axis=1)
这应该会产生一个向量,其条目只有一个。
更详细地说,np.ma.masked_equal(matrix, 0)
的输出应该如下所示:
masked_array(data =
[[1.0 -- -- -- --]
[1.0 1.0 -- -- --]
[1.0 1.0 1.0 -- --]
[1.0 1.0 1.0 1.0 --]
[1.0 1.0 1.0 1.0 1.0]],
mask =
[[False True True True True]
[False False True True True]
[False False False True True]
[False False False False True]
[False False False False False]],
fill_value = 0.0)
这表明 --
上的 eh 值被认为是无效的。这也在掩码数组的掩码属性中显示为 True ,这表明它是一个无效元素,因此应该被忽略。
最终对该数组进行均值运算的输出应该是:
masked_array(data = [1.0 1.0 1.0 1.0 1.0],
mask = [False False False False False],
fill_value = 1e+20)
我有一个大小为 N*M 的矩阵,我想求出每一行的平均值。值从 1 到 5,没有任何值的条目设置为 0。但是,当我想使用以下方法找到平均值时,它给了我错误的平均值,因为它还计算了值为0.
matrix_row_mean= matrix.mean(axis=1)
我怎样才能得到非零值的平均值?
获取每行中非零的计数,并将其用于计算每行求和的平均值。因此,实现看起来像这样 -
np.true_divide(matrix.sum(1),(matrix!=0).sum(1))
如果你使用的是旧版本的 NumPy,你可以使用计数的浮点数转换来替换 np.true_divide
,就像这样 -
matrix.sum(1)/(matrix!=0).sum(1).astype(float)
样本运行-
In [160]: matrix
Out[160]:
array([[0, 0, 1, 0, 2],
[1, 0, 0, 2, 0],
[0, 1, 1, 0, 0],
[0, 2, 2, 2, 2]])
In [161]: np.true_divide(matrix.sum(1),(matrix!=0).sum(1))
Out[161]: array([ 1.5, 1.5, 1. , 2. ])
另一种解决问题的方法是用 NaNs
替换零,然后使用 np.nanmean
,这将忽略那些 NaNs
,实际上那些原始的 zeros
, 像这样 -
np.nanmean(np.where(matrix!=0,matrix,np.nan),1)
从性能的角度来看,我会推荐第一种方法。
我将在这里详细说明使用 masked array 的更通用的解决方案。为了说明细节,让我们创建一个只有一个的下三角矩阵:
matrix = np.tril(np.ones((5, 5)), 0)
如果您对上面的术语不清楚,则此矩阵如下所示:
[[ 1., 0., 0., 0., 0.],
[ 1., 1., 0., 0., 0.],
[ 1., 1., 1., 0., 0.],
[ 1., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1.]]
现在,我们希望我们的函数 return 每行的平均值为 1。或者换句话说,轴 1 上的平均值等于五个 1 的向量。为了实现这一点,我们创建了一个屏蔽矩阵 ,其中值为零的条目被视为无效 。这可以通过 np.ma.masked_equal
:
masked = np.ma.masked_equal(matrix, 0)
最后,我们在此数组中执行 numpy 操作,系统地忽略被屏蔽的元素(0)。考虑到这一点,我们通过以下方式获得所需的结果:
masked.mean(axis=1)
这应该会产生一个向量,其条目只有一个。
更详细地说,np.ma.masked_equal(matrix, 0)
的输出应该如下所示:
masked_array(data =
[[1.0 -- -- -- --]
[1.0 1.0 -- -- --]
[1.0 1.0 1.0 -- --]
[1.0 1.0 1.0 1.0 --]
[1.0 1.0 1.0 1.0 1.0]],
mask =
[[False True True True True]
[False False True True True]
[False False False True True]
[False False False False True]
[False False False False False]],
fill_value = 0.0)
这表明 --
上的 eh 值被认为是无效的。这也在掩码数组的掩码属性中显示为 True ,这表明它是一个无效元素,因此应该被忽略。
最终对该数组进行均值运算的输出应该是:
masked_array(data = [1.0 1.0 1.0 1.0 1.0],
mask = [False False False False False],
fill_value = 1e+20)