我试图找到使用pandas进行矩阵乘法的最佳方法。假设我想做一个简单的练习:xyx'... [1x5] [5x5] [5x1]'。
in:
ydates = pd.date_range('20170101',periods=5)
y = pd.DataFrame(np.identity(5),index=['f','o','b','a','r'],columns=['f','o','b','a','r'])
xdata = list(range(1,6))
x = pd.DataFrame(xdata,index=['f','o','b','a','r'])
x.loc['o'] = np.nan
mm = x.T.dot(y)*x.T
out:
f o b a r
0 NaN NaN NaN NaN NaN
我希望得到:
0
f 1.0
o NaN
b 3.0
a 4.0
r 5.0
我的问题是:
1)如何对齐这些?有没有比做双重转置更好的方法?
2)有没有办法解释nans?
2)使用python / pandas进行矩阵代数是否有更有效的方法?
答案 0 :(得分:0)
numpy
有几个处理矩阵产品的函数 - np.dot
,np.einsum
和np.matmul
(以及@
运算符)。 *
被定义为元素乘法(np.matrix
类除外)。所有都针对速度进行了优化但他们也传播nan
。
使用numpy数组而不是pandas:
In [314]: y = np.eye(5)
In [316]: y
Out[316]:
array([[ 1., 0., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 1.]])
要在x
进行转置,我们需要将其设为2d;并指定nan
它必须是浮动的。
In [320]: x = np.arange(1,6).astype(float).reshape(1,5)
In [321]: x[0,1]=np.nan
In [322]: x
Out[322]: array([[ 1., nan, 3., 4., 5.]])
In [323]: x.T # column vector
Out[323]:
array([[ 1.],
[ nan],
[ 3.],
[ 4.],
[ 5.]])
In [324]: np.dot(y, x.T)
Out[324]:
array([[ nan],
[ nan],
[ nan],
[ nan],
[ nan]])
为什么会出现dot
结果?它将y
的每一行乘以x.T
的列,并对这些值求和。由于nan
每行的y
个产品之一为1*nan
或0*nan
;涉及nan
的任何产品或总和产生nan
,结果全部为nan
。
我怀疑你希望0*nan == 0
。像:
In [329]: x[0,1]=100
In [330]: np.dot(y, x.T)
Out[330]:
array([[ 1.],
[ 100.],
[ 3.],
[ 4.],
[ 5.]])
有些numpy
个函数会跳过nan
。 np.dot
不是其中之一。
In [333]: x[0,1]=np.nan
In [336]: y*x
Out[336]:
array([[ 1., nan, 0., 0., 0.],
[ 0., nan, 0., 0., 0.],
[ 0., nan, 3., 0., 0.],
[ 0., nan, 0., 4., 0.],
[ 0., nan, 0., 0., 5.]])
In [339]: np.nansum(y*x, axis=1, keepdims=True)
Out[339]:
array([[ 1.],
[ 0.],
[ 3.],
[ 4.],
[ 5.]])
这种作品。在对行进行求和时,它跳过nan
;但第二个值是0,而不是nan
。
np.nan...
函数的工作原理是暂时将nan
替换为无关紧要的内容,例如0或1.我可以在您的情况下执行以下操作:
In [369]: x
Out[369]: array([[ 1., nan, 3., 4., 5.]])
In [370]: x1, mask = np.lib.nanfunctions._replace_nan(x.T,1)
In [371]: x1
Out[371]:
array([[ 1.],
[ 1.],
[ 3.],
[ 4.],
[ 5.]])
In [372]: mask
Out[372]:
array([[False],
[ True],
[False],
[False],
[False]], dtype=bool)
In [373]: x2 = np.dot(y, x1)
In [374]: x2[mask] = np.nan
In [375]: x2
Out[375]:
array([[ 1.],
[ nan],
[ 3.],
[ 4.],
[ 5.]])