gpt4 book ai didi

python - 使用 2 个索引列表对 2D Numpy 数组进行索引

转载 作者:IT老高 更新时间:2023-10-28 21:17:48 25 4
gpt4 key购买 nike

我遇到了一个奇怪的情况。

我有一个 2D Numpy 数组,x:

x = np.random.random_integers(0,5,(20,8))

我有 2 个索引器——一个带有行索引,一个带有列索引。为了索引 X,我必须执行以下操作:

row_indices = [4,2,18,16,7,19,4]
col_indices = [1,2]
x_rows = x[row_indices,:]
x_indexed = x_rows[:,column_indices]

不仅仅是:

x_new = x[row_indices,column_indices]

(失败并出现:错误,不能用(2,)广播(20,))


我希望能够使用广播在一行中进行索引,因为这样可以使代码保持干净和可读......而且,我不太了解 python 的底层知识,但是据我了解,在一行中完成它应该更快(我将使用相当大的数组)。


测试用例:

x = np.random.random_integers(0,5,(20,8))

row_indices = [4,2,18,16,7,19,4]
col_indices = [1,2]
x_rows = x[row_indices,:]
x_indexed = x_rows[:,col_indices]

x_doesnt_work = x[row_indices,col_indices]

最佳答案

使用索引或 bool 数组/掩码通过 np.ix_ 进行选择或赋值

1。使用 indexing-arrays

A.选择

我们可以使用 np.ix_获得一个可相互广播的索引数组元组,以产生更高维的索引组合。因此,当该元组用于索引输入数组时,将给我们相同的高维数组。因此,要根据两个 1D 索引数组进行选择,应该是 -

x_indexed = x[np.ix_(row_indices,col_indices)]

B.作业

我们可以使用相同的符号将标量或可广播数组分配到这些索引位置。因此,以下适用于作业 -

x[np.ix_(row_indices,col_indices)] = # scalar or broadcastable array

2。带掩码

我们还可以在 np.ix_ 中使用 bool 数组/掩码,类似于使用索引数组的方式。这可以再次用于从输入数组中选择一个 block ,也可以用于分配给它。

A.选择

因此,使用 row_maskcol_mask bool 数组分别作为行和列选择的掩码,我们可以使用以下选择 -

x[np.ix_(row_mask,col_mask)]

B.作业

以下适用于作业 -

x[np.ix_(row_mask,col_mask)] = # scalar or broadcastable array

样本运行

1.将 np.ix_indexing-arrays

一起使用

输入数组和索引数组 -

In [221]: x
Out[221]:
array([[17, 39, 88, 14, 73, 58, 17, 78],
[88, 92, 46, 67, 44, 81, 17, 67],
[31, 70, 47, 90, 52, 15, 24, 22],
[19, 59, 98, 19, 52, 95, 88, 65],
[85, 76, 56, 72, 43, 79, 53, 37],
[74, 46, 95, 27, 81, 97, 93, 69],
[49, 46, 12, 83, 15, 63, 20, 79]])

In [222]: row_indices
Out[222]: [4, 2, 5, 4, 1]

In [223]: col_indices
Out[223]: [1, 2]

带有 np.ix_ 的索引数组元组 -

In [224]: np.ix_(row_indices,col_indices) # Broadcasting of indices
Out[224]:
(array([[4],
[2],
[5],
[4],
[1]]), array([[1, 2]]))

做出选择 -

In [225]: x[np.ix_(row_indices,col_indices)]
Out[225]:
array([[76, 56],
[70, 47],
[46, 95],
[76, 56],
[92, 46]])

作为 suggested by OP ,这实际上与使用 row_indices 的 2D 数组版本执行 old-school 广播相同,其元素/索引 sentaxis=0 并因此在 axis=1 处创建一个单一维度,从而允许使用 col_indices 进行广播。因此,我们会有这样的替代解决方案 -

In [227]: x[np.asarray(row_indices)[:,None],col_indices]
Out[227]:
array([[76, 56],
[70, 47],
[46, 95],
[76, 56],
[92, 46]])

如前所述,对于分配,我们只是这样做。

行、列索引数组-

In [36]: row_indices = [1, 4]

In [37]: col_indices = [1, 3]

使用标量进行赋值 -

In [38]: x[np.ix_(row_indices,col_indices)] = -1

In [39]: x
Out[39]:
array([[17, 39, 88, 14, 73, 58, 17, 78],
[88, -1, 46, -1, 44, 81, 17, 67],
[31, 70, 47, 90, 52, 15, 24, 22],
[19, 59, 98, 19, 52, 95, 88, 65],
[85, -1, 56, -1, 43, 79, 53, 37],
[74, 46, 95, 27, 81, 97, 93, 69],
[49, 46, 12, 83, 15, 63, 20, 79]])

使用 2D block (可广播的数组)进行分配 -

In [40]: rand_arr = -np.arange(4).reshape(2,2)

In [41]: x[np.ix_(row_indices,col_indices)] = rand_arr

In [42]: x
Out[42]:
array([[17, 39, 88, 14, 73, 58, 17, 78],
[88, 0, 46, -1, 44, 81, 17, 67],
[31, 70, 47, 90, 52, 15, 24, 22],
[19, 59, 98, 19, 52, 95, 88, 65],
[85, -2, 56, -3, 43, 79, 53, 37],
[74, 46, 95, 27, 81, 97, 93, 69],
[49, 46, 12, 83, 15, 63, 20, 79]])

<强>2。将 np.ix_masks

一起使用

输入数组-

In [19]: x
Out[19]:
array([[17, 39, 88, 14, 73, 58, 17, 78],
[88, 92, 46, 67, 44, 81, 17, 67],
[31, 70, 47, 90, 52, 15, 24, 22],
[19, 59, 98, 19, 52, 95, 88, 65],
[85, 76, 56, 72, 43, 79, 53, 37],
[74, 46, 95, 27, 81, 97, 93, 69],
[49, 46, 12, 83, 15, 63, 20, 79]])

输入行,列掩码 -

In [20]: row_mask = np.array([0,1,1,0,0,1,0],dtype=bool)

In [21]: col_mask = np.array([1,0,1,0,1,1,0,0],dtype=bool)

做出选择 -

In [22]: x[np.ix_(row_mask,col_mask)]
Out[22]:
array([[88, 46, 44, 81],
[31, 47, 52, 15],
[74, 95, 81, 97]])

使用标量进行赋值 -

In [23]: x[np.ix_(row_mask,col_mask)] = -1

In [24]: x
Out[24]:
array([[17, 39, 88, 14, 73, 58, 17, 78],
[-1, 92, -1, 67, -1, -1, 17, 67],
[-1, 70, -1, 90, -1, -1, 24, 22],
[19, 59, 98, 19, 52, 95, 88, 65],
[85, 76, 56, 72, 43, 79, 53, 37],
[-1, 46, -1, 27, -1, -1, 93, 69],
[49, 46, 12, 83, 15, 63, 20, 79]])

使用 2D block (可广播的数组)进行分配 -

In [25]: rand_arr = -np.arange(12).reshape(3,4)

In [26]: x[np.ix_(row_mask,col_mask)] = rand_arr

In [27]: x
Out[27]:
array([[ 17, 39, 88, 14, 73, 58, 17, 78],
[ 0, 92, -1, 67, -2, -3, 17, 67],
[ -4, 70, -5, 90, -6, -7, 24, 22],
[ 19, 59, 98, 19, 52, 95, 88, 65],
[ 85, 76, 56, 72, 43, 79, 53, 37],
[ -8, 46, -9, 27, -10, -11, 93, 69],
[ 49, 46, 12, 83, 15, 63, 20, 79]])

关于python - 使用 2 个索引列表对 2D Numpy 数组进行索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35607818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com