从numpy矩阵中去除均值
我有一个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.]])