使用NumPy和Python中类似R或MATLAB的语法更新子矩阵
我是一个R用户,我正在学习Python(尤其是numpy),但我不能用Python执行更新子矩阵的简单任务,这在R中很容易完成 所以我有两个问题 第一个是假设我们有一个4乘4的矩阵使用NumPy和Python中类似R或MATLAB的语法更新子矩阵,python,arrays,numpy,matrix,Python,Arrays,Numpy,Matrix,我是一个R用户,我正在学习Python(尤其是numpy),但我不能用Python执行更新子矩阵的简单任务,这在R中很容易完成 所以我有两个问题 第一个是假设我们有一个4乘4的矩阵 A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]) 和一个2乘2的矩阵 B = np.array([[100,200],[300,400]]). 我想获取一个2乘2的a子矩阵,该子矩阵由第2行和第4行和第4列(array([[6,8][14
A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
和一个2乘2的矩阵
B = np.array([[100,200],[300,400]]).
我想获取一个2乘2的a
子矩阵,该子矩阵由第2行和第4行和第4列(array([[6,8][14,16]])
)构成,并将其替换为B
我可以通过执行以下操作来提取正确的矩阵
m = [1,3]
A[m][:,m]
但是A
即使在我将其更新为B
之后,也不会发生任何事情。就是
A[m][:,m] = B
print A
而A
结果是一样的
有没有一种方法不使用循环或使用相对简单的代码来实现这一点
第二个相对容易的问题是,在R中,我们可以用True
和False
来子集矩阵。从上面的A
,我们可以通过
m = [F, T, F, T]
A[m,m]
但是,在Python中,相同的代码似乎不起作用,因为True
为1而False
为0。我认为我可以将[F,T,F,T]
转换为[1,3]
和子集,但我认为可能有一个单步方法来实现这一点
当索引以True
和False
的形式给出时,Python中是否有一种简单的方法来执行相同的操作?对于第1部分,从中,有一些示例显示了对任意切片的只读和可变访问
只读模式类似于您已经描述的,A[:,m][m]
。这将首先对列进行切片,然后对行进行切片,并提供返回数据的只读视图
为了获得用于突变子数组的干净索引,提供了一个方便的函数,np.ix
。它将把参数拼接成一个类似R或MATLAB的切片:
indxs = np.ix_([1,3], [1,3])
A[indxs] = B
这背后的原因是NumPy遵循特定的形状一致性规则(称为“广播”规则),关于如何根据数据中存在的形状推断您想要的形状。当NumPy对行索引和列索引对执行此操作时,它会尝试按元素对它们进行配对
因此,在NumPy选择的约定下,A[[1,3],[1,3]]
被解释为“在索引(1,1)和索引(3,3)处为我获取A
的值”,这与MATLAB、倍频程或R中相同语法的约定不同
如果您想在不使用np.ix_uuu
的情况下手动绕过此问题,您仍然可以,但您必须写下索引以利用NumPy的广播规则。这意味着你必须给NumPy一个理由,让它相信你想要一个2x2的索引网格,而不是两个特定点的1x2列表
您可以通过将您的行条目设置为列表本身来欺骗它:rows=[[1],[3]]
。现在,当NumPy检查这个形状(1 x 2而不是1 x nothing)时,它会说,‘啊哈,列最好也是1 x 2’,并自动提升列列表,以分别与每个可能的行匹配。这就是为什么这也会起作用:
A[[[1], [3]], [1, 3]] = B
对于问题的第二部分,问题是您想让NumPy知道您的[False,True,False,True]
数组是一个布尔数组,不应隐式转换为任何其他类型的数组
这可以通过多种方式完成,但一种简单的方法是构造布尔值的np.array
,其dtype
将是bool
:
indxs = np.array([False, True, False, True])
print A[:, indxs][indxs] # remember, this one is read only
A[np.ix_(indxs, indxs)] = B
另一个有用的NumPy便利工具是np.s\uucode>,它不是函数(它是NumPy.lib.index\u tricks.IndexExpression
的一个实例),但可以像函数一样使用
np.s
允许您使用元素获取语法(在Python中称为getitem语法,在任何新样式的类实例都将具有的\uuuuuuuu getitem\uuuu
方法之后)。举例来说:
In [60]: np.s_[[1,3], [1,3]]
Out[60]: ([1, 3], [1, 3])
In [61]: np.s_[np.ix_([1,3], [1,3])]
Out[61]:
(array([[1],
[3]]), array([[1, 3]]))
In [62]: np.s_[:, [1,3]]
Out[62]: (slice(None, None, None), [1, 3])
In [63]: np.s_[:, :]
Out[63]: (slice(None, None, None), slice(None, None, None))
In [64]: np.s_[-1:1:-2, :]
Out[64]: (slice(-1, 1, -2), slice(None, None, None))
因此,np.s
基本上只是镜像回切片索引对象的外观,如果您将其放在方括号内以访问某些数组的数据
特别是,前两个np.s_uuu
示例向您展示了普通A[[1,3],[1,3]]
和np.ix_uu([1,3],[1,3])的使用之间的区别
以及它们是如何产生不同的部分的。你能详细解释一下第二个问题的答案吗?我只是在这一部分增加了一点。您还应该使用一些数组的dtype
属性来了解NumPy认为这些类型是什么。在使用它一段时间后,您将直观地知道NumPy何时何地代表您尝试将值转换为新类型,例如它试图将[False,True,False,True]的普通列表
视为整数(如果可以的话),但如果它们位于ndarray
中,且dtype
设置为bool
,则它们将保留为bool
值。非常感谢!这就是我想要的。