从numpy矩阵中去除均值

25 投票
4 回答
32137 浏览
提问于 2025-04-17 07:55

我有一个numpy矩阵A,里面的数据是按列组织的,也就是说A[:,0]是第一列的数据,A[:,1]是第二列的数据,以此类推。我想知道有没有更优雅的方法来把这些数据的平均值变成零。目前我是通过一个for循环来实现的:

mean=A.mean(axis=1)
for k in range(A.shape[1]):
    A[:,k]=A[:,k]-mean

那么,numpy有没有提供一个函数来做到这一点?或者有没有其他更高效的方法?

4 个回答

5

是的。pylab.demean

In [1]: X = scipy.rand(2,3)

In [2]: X.mean(axis=1)
Out[2]: array([ 0.42654669,  0.65216704])

In [3]: Y = pylab.demean(X, axis=1)

In [4]: Y.mean(axis=1)
Out[4]: array([  1.85037171e-17,   0.00000000e+00])

来源:

In [5]: pylab.demean??
Type:           function
Base Class:     <type 'function'>
String Form:    <function demean at 0x38492a8>
Namespace:      Interactive
File:           /usr/lib/pymodules/python2.7/matplotlib/mlab.py
Definition:     pylab.demean(x, axis=0)
Source:
def demean(x, axis=0):
    "Return x minus its mean along the specified axis"
    x = np.asarray(x)
    if axis == 0 or axis is None or x.ndim <= 1:
        return x - x.mean(axis)
    ind = [slice(None)] * x.ndim
    ind[axis] = np.newaxis
    return x - x.mean(axis)[ind]
11

你也可以用 matrix 来代替 array。这样的话,你就不需要重新调整形状了:

>>> A = np.matrix([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
>>> m = A.mean(axis=1)
>>> A - m
matrix([[-1.,  0.,  1.],
        [-1.,  0.,  1.],
        [-1.,  0.,  1.],
        [-1.,  0.,  1.]])
38

通常来说,你可以用很多方法来实现这个功能。下面每种方法都是通过给 mean 向量增加一个维度,把它变成一个 4 x 1 的数组,然后 NumPy 的广播功能会处理剩下的事情。每种方法创建的都是 mean 的视图,而不是深拷贝。第一种方法(也就是使用 newaxis)可能是大多数人更喜欢的,但其他方法也在这里列出以供参考。

除了下面的方法,你还可以看看 ovgolovin 的回答,它使用 NumPy 矩阵来避免完全重塑 mean

对于下面的方法,我们先从以下代码和示例数组 A 开始。

import numpy as np

A = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
mean = A.mean(axis=1)

使用 numpy.newaxis

>>> A - mean[:, np.newaxis]
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.]])

使用 None

文档中提到可以用 None 来代替 newaxis。这是因为

>>> np.newaxis is None
True

因此,下面的代码也能完成这个任务。

>>> A - mean[:, None]
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.]])

不过,newaxis 更清晰,应该优先使用。此外,有人认为 newaxis 更具未来兼容性。还可以参考:Numpy: 我应该使用 newaxis 还是 None?

使用 ndarray.reshape

>>> A - mean.reshape((mean.shape[0]), 1)
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.]])

直接改变 ndarray.shape

你也可以直接改变 mean 的形状。

>>> mean.shape = (mean.shape[0], 1)
>>> A - mean
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.],
       [-1.,  0.,  1.]])

撰写回答