我是一个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]]).
我想获取A
的一个2 × 2子矩阵(array([[6,8][14,16]])
),并将其替换为B
,其中A
由第2行和第4列组成。
我可以通过以下操作得到正确的矩阵
m = [1,3]
A[m][:,m]
但是A
没有任何变化,即使我将它更新为B
。
A[m][:,m] = B
print A
并且A
结果是相同的。
有没有一种方法可以做到这一点,而不使用循环或可能与一个相对简单的代码?
第二个相对简单的问题是,在R中,我们可以用True
和False
子集化矩阵,从上面的A
,我们可以用下式子集化相同的2 × 2矩阵
m = [F, T, F, T]
A[m,m]
然而,在Python中,相同的代码似乎不起作用,因为True
是1,False
是0。我认为我可以将[F,T,F,T]
转换为[1,3]
和子集,但我认为可能有一个一步完成的方法。
当索引是以True
和False
的形式给出时,在Python中有没有简单的方法来执行相同的操作?
1条答案
按热度按时间xqk2d5yq1#
对于第1部分,从NumPy for MATLAB Users开始,有一些示例显示了对任意片的只读访问和可变访问。
只读模式类似于您已经描述过的
A[:, m][m]
,它首先对列进行切片,然后对行进行切片,并提供返回数据的只读视图。为了获得用于修改子数组的干净索引,我们提供了一个方便的函数
np.ix_
,它将其参数拼接成一个类似R或类似MATLAB的切片:这背后的原因是NumPy遵循某些形状一致性规则(称为“广播”规则),这些规则涉及如何根据数据中存在的形状推断所需的形状。当NumPy对行索引和列索引对执行此操作时,它会尝试按元素对它们进行配对。
因此,
A[[1, 3], [1, 3]]
在NumPy选择的约定下被解释为“为我获取索引(1,1)和索引(3,3)处的A
的值”,这与MATLAB、Octave或R中相同语法的约定不同。如果你想手动解决这个问题,不用
np.ix_
,你仍然可以,但是你必须写下你的索引来利用NumPy的广播规则,这意味着你必须给予NumPy一个理由,让他相信你想要一个2x2的索引网格,而不是一个1x2的两个特定点的列表。你可以通过把你的行条目放到列表中来欺骗它相信这一点:
rows = [[1], [3]]
。现在当NumPy检查它的形状(1 x 2而不是1 x nothing)时,它会说,“啊哈,列最好也是1 x 2”,并自动提升列列表,使其与每个可能的行单独匹配。这就是为什么这也会起作用:对于问题的第二部分,问题是您希望让NumPy知道您的
[False, True, False, True]
数组是布尔数组,不应该隐式转换为任何其他类型的数组。这可以通过许多方法来实现,但一个简单的方法是构造一个布尔值的
np.array
,它的dtype
将是bool
:另一个有用的NumPy便利工具是
np.s_
,它不是一个函数(它是numpy.lib.index_tricks.IndexExpression
的一个示例),但可以像函数一样使用。np.s_
允许你使用元素获取语法(在Python中叫做 getitem 语法,在__getitem__
方法之后,任何新式的类示例都会有)。所以
np.s_
基本上只是镜像回切片索引对象的样子,如果你把它放在方括号里,以访问一些数组的数据。特别是,前两个
np.s_
示例向您展示了普通A[[1,3], [1,3]]
和使用np.ix_([1,3], [1,3])
之间的区别,以及它们如何产生不同的切片。