python - 在 NumPy 和 Python 中使用类似 R 或类似 MATLAB 的语法更新子矩阵

标签 python arrays numpy matrix

我是 R 用户,我正在学习 Python(尤其是 numpy),但我无法在 Python 中执行更新子矩阵的简单任务,而这在 R 中可以很容易地完成。

所以我有两个问题。

第一个是说我们有一个 4 x 4 矩阵

A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])

和一个 2 x 2 矩阵

B = np.array([[100,200],[300,400]]).

我想获取 A 的 2 x 2 子矩阵,该子矩阵由第 2 行和第 4 行和列组成 (array([[6,8][14,16]])) 并将其替换为 B

我可以拉出正确的矩阵

m = [1,3]
A[m][:,m]

但即使在我将其更新为 B 之后,A 也没有任何变化。也就是

A[m][:,m] = B
print A

A结果是一样的。

有没有一种方法可以不使用循环或者使用相对简单的代码来做到这一点?

第二个相对容易的问题是,在 R 中,我们可以用 TrueFalse 对矩阵进行子集化。从上面的 A,我们可以通过

对相同的 2×2 矩阵进行子集化
m = [F, T, F, T]
A[m,m]

但是,在 Python 中,相同的代码似乎不起作用,因为 True 是 1 而 False 是 0。我想我可以转换 [F,T ,F,T][1,3] 和子集,但我认为可能有一种一步法可以做到这一点。

当根据 TrueFalse 给出索引时,是否有一种简单的方法可以在 Python 中执行相同的操作?

最佳答案

对于第 1 部分,来自 NumPy for MATLAB Users ,有一些示例显示了对任意切片的只读和可变访问。

只读模式类似于您已经描述的A[:, m][m]。这首先对列进行切片,然后对行进行切片,并提供返回数据的只读 View 。

为了获得用于改变子数组的干净索引,提供了一个方便的函数,np.ix_。它将其参数拼接成一个类似 R 或类似 MATLAB 的切片:

indxs = np.ix_([1,3], [1,3])
A[indxs] = B

这背后的原因是 NumPy 遵循某些形状一致性规则(称为“广播”规则)关于如何根据数据中存在的形状推断您想要的形状。当 NumPy 对行索引和列索引对执行此操作时,它会尝试按元素将它们配对。

因此 A[[1, 3], [1, 3]] 在 NumPy 选择的约定下,被解释为“为我获取索引处 A 的值(1,1) 和索引 (3,3)。”这与 MATLAB、Octave 或 R 中相同语法的约定不同。

如果你想手动解决这个问题,没有 np.ix_,你仍然可以,但你必须写下你的索引以利用 NumPy 的广播规则。这意味着您必须给 NumPy 一个理由,让您相信您需要一个 2x2 的索引网格,而不是两个特定点的 1x2 列表。

您可以通过将您的行条目放入列表本身来欺骗它相信这一点:rows = [[1], [3]]。现在,当 NumPy 检查它的形状(1 x 2 而不是 1 x 什么都没有)时,它会说,'啊哈,列最好也是 1 x 2',并自动提升列列表以与每个可能的行单独匹配。这就是为什么这也会起作用:

A[[[1], [3]], [1, 3]] = B

对于问题的第二部分,问题是您想让 NumPy 知道您的 [False, True, False, True] 数组是一个 bool 数组,不应隐式转换为任何其他类型的数组。

这可以通过多种方式完成,但一种简单的方法是构造一个 bool 值的 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_,它不是函数(它是 numpy.lib.index_tricks.IndexExpression 的实例)但可以使用有点像。

np.s_ 允许您使用元素获取语法(在 Python 中称为 getitem 语法,在任何新的 __getitem__ 方法之后-style 类实例将具有)。举个例子:

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_ 基本上只是反射(reflect)了切片索引对象的样子,如果您将它放在方括号内以访问某些数组的数据。

特别是前两个 np.s_ 示例向您展示了普通 A[[1,3], [1,3]]np.ix_([1,3], [1,3]) 的使用以及它们如何产生不同的切片。

关于python - 在 NumPy 和 Python 中使用类似 R 或类似 MATLAB 的语法更新子矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28509551/

相关文章:

python - webbrowser python 在同一选项卡中打开新的 url。这有用吗?

Python 正则表达式 AttributeError : 'NoneType' object has no attribute 'group'

python - 我知道我应该将 Python 代码保持在 79 列,但我如何缩进连续的行?

javascript - 将枚举对象转换为数组在 javascript 中返回额外的对象

python - 将图像数组从 Python 传递到 C 会带来损坏的数据

python |获取二维列表的第一个元素

c# - 扩展数组的最快方法

C:指向二维指针数组的指针

python - 用 numPy 数组中的整数替换 bool 值

python - 与 Numpy 相比优化 Cython 循环