如何使用numpy?如何快速在二维矩阵中选择子矩阵。

发布于 2025-01-19 00:10:45 字数 745 浏览 0 评论 0原文

我有一个 7×7 矩阵,我不想使用循环来快速切出子矩阵。

matrix= array([[ 0,  1,  2,  3,  4,  5,  6],
   [ 7,  8,  9, 10, 11, 12, 13],
   [14, 15, 16, 17, 18, 19, 20],
   [21, 22, 23, 24, 25, 26, 27],
   [28, 29, 30, 31, 32, 33, 34],
   [35, 36, 37, 38, 39, 40, 41],
   [42, 43, 44, 45, 46, 47, 48]])

sub_matrix = array([[1,2,3], [16,17,18], [28,29,30], [39,40,41]])

原理图

其实这个矩阵很大。我有每行的切片列表和每列开头的切片列表。直接指定所有行的列切片列表是非常困难的。

我尝试了以下方法,但它给了我错误:IndexError:形状不匹配:索引数组无法与形状(4,)(4,3)一起广播

slice_row = [0, 2, 4, 5]
slice_col_start = [1,2,0,4]
interval = 3
slice_col = [np.arange(x,x+interval) for x in slice_col_start]

matrix[slice_row, np.r_[slice_col]]

I have a 7×7 matrix and I don't want to use the loop to quickly slice out a submatrix.

matrix= array([[ 0,  1,  2,  3,  4,  5,  6],
   [ 7,  8,  9, 10, 11, 12, 13],
   [14, 15, 16, 17, 18, 19, 20],
   [21, 22, 23, 24, 25, 26, 27],
   [28, 29, 30, 31, 32, 33, 34],
   [35, 36, 37, 38, 39, 40, 41],
   [42, 43, 44, 45, 46, 47, 48]])

sub_matrix = array([[1,2,3], [16,17,18], [28,29,30], [39,40,41]])

Principle picture

In fact, this matrix is very large. I have a list of slices per row and a list of slices at the beginning of each column. It is very difficult to specify directly the columns slice list for all rows.

I tried the following method, but it gave me error:IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (4,3)

slice_row = [0, 2, 4, 5]
slice_col_start = [1,2,0,4]
interval = 3
slice_col = [np.arange(x,x+interval) for x in slice_col_start]

matrix[slice_row, np.r_[slice_col]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

朕就是辣么酷 2025-01-26 00:10:45

如果您有索引可以执行:

x = np.array([[1,2,3], [2,3,4], [0,1,2], [4,5,6]])
y = np.array([0, 2, 4, 5])
matrix[y[:,None], x]

输出:

array([[ 1,  2,  3],
       [16, 17, 18],
       [28, 29, 30],
       [39, 40, 41]])

If you have the indices you could do:

x = np.array([[1,2,3], [2,3,4], [0,1,2], [4,5,6]])
y = np.array([0, 2, 4, 5])
matrix[y[:,None], x]

output:

array([[ 1,  2,  3],
       [16, 17, 18],
       [28, 29, 30],
       [39, 40, 41]])
︶ ̄淡然 2025-01-26 00:10:45
In [11]: arr = np.arange(49).reshape(7,7)
In [12]: slice_row = [0, 2, 4, 5]
    ...: slice_col_start = [1,2,0,4]
    ...: interval = 3
In [13]: idx1 = np.array(slice_row)
In [14]: idx2 = np.array(slice_col_start)

由于间隔是固定的,因此我们可以使用linspace用一个调用来创建所有列索引:

In [19]: idx3 = np.linspace(idx2,idx2+interval, interval, endpoint=False,dtype=int)
In [20]: idx3
Out[20]: 
array([[1, 2, 0, 4],
       [2, 3, 1, 5],
       [3, 4, 2, 6]])

然后,这只是索引的问题:

In [21]: arr[idx1[:,None], idx3.T]
Out[21]: 
array([[ 1,  2,  3],
       [16, 17, 18],
       [28, 29, 30],
       [39, 40, 41]])

或使用广播添加:

In [23]: idx2[:,None] + np.arange(3)
Out[23]: 
array([[1, 2, 3],
       [2, 3, 4],
       [0, 1, 2],
       [4, 5, 6]])

如果间隔因行而变化,我们将不得不使用迭代形式获取完整的列索引列表。

In [11]: arr = np.arange(49).reshape(7,7)
In [12]: slice_row = [0, 2, 4, 5]
    ...: slice_col_start = [1,2,0,4]
    ...: interval = 3
In [13]: idx1 = np.array(slice_row)
In [14]: idx2 = np.array(slice_col_start)

Since the interval is fixed, we can use linspace to create all column indices with one call:

In [19]: idx3 = np.linspace(idx2,idx2+interval, interval, endpoint=False,dtype=int)
In [20]: idx3
Out[20]: 
array([[1, 2, 0, 4],
       [2, 3, 1, 5],
       [3, 4, 2, 6]])

Then it's just a matter of indexing:

In [21]: arr[idx1[:,None], idx3.T]
Out[21]: 
array([[ 1,  2,  3],
       [16, 17, 18],
       [28, 29, 30],
       [39, 40, 41]])

Or use broadcasted addition:

In [23]: idx2[:,None] + np.arange(3)
Out[23]: 
array([[1, 2, 3],
       [2, 3, 4],
       [0, 1, 2],
       [4, 5, 6]])

If the interval varies by row, we will have to use form of iteration to get the full list of column indices.

染墨丶若流云 2025-01-26 00:10:45

可以通过np.take_along_axis来实现。如果给出cols数组:

rows = np.array([0, 2, 4, 5], dtype=np.int32)
cols = np.array([[1,2,3], [2,3,4], [0,1,2], [4,5,6]])
result = np.take_along_axis(a[rows], cols, axis=1)

It can be achieved by np.take_along_axis. If the cols array be given:

rows = np.array([0, 2, 4, 5], dtype=np.int32)
cols = np.array([[1,2,3], [2,3,4], [0,1,2], [4,5,6]])
result = np.take_along_axis(a[rows], cols, axis=1)
土豪 2025-01-26 00:10:45

感谢凯文,我想出了一个解决方案

import numpy as np
matrix = np.arange(7*7).reshape(7,7)
slice_row = np.array([0, 2, 4, 5])
slice_col_start = np.array([1,2,0,4])
interval = 3
slice_col = [np.arange(x,x+interval).tolist() for x in slice_col_start]

sub_matrix =matrix[slice_row[:,None], slice_col]
print(sub_matrix)

输出

[[ 1  2  3]
 [16 17 18]
 [28 29 30]
 [39 40 41]]

Thanks to Kevin, I came up with a solution

import numpy as np
matrix = np.arange(7*7).reshape(7,7)
slice_row = np.array([0, 2, 4, 5])
slice_col_start = np.array([1,2,0,4])
interval = 3
slice_col = [np.arange(x,x+interval).tolist() for x in slice_col_start]

sub_matrix =matrix[slice_row[:,None], slice_col]
print(sub_matrix)

output

[[ 1  2  3]
 [16 17 18]
 [28 29 30]
 [39 40 41]]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文