Writting in sub-ndarray of a ndarray in the most pythonian way. Python 2

坚强是说给别人听的谎言 提交于 2019-12-02 09:01:44

问题


I have a ndarray like this one:

number_of_rows = 3
number_of_columns = 3
a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns)
a

array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

But I want something like this:

array([[0, 100, 101],
       [3, 102, 103],
       [6, 7, 8]])

To do that I want to avoid to do it one by one, I rather prefer to do it in arrays or matrices, because later I want to extend the code. Nothe I have change a submatrix of the initial matrix (in mathematical terms, in terms of this example ndarray). In the example the columns considered are [1,2] and the rows [0,1].

columns_to_keep = [1,2] 
rows_to_keep = [0,1]

My first try was to do:

a[rows_to_keep,:][:,columns_to_keep] = np.asarray([[100,101],[102,103]])

However this doesn't modify the initial a, I am not having any error, so a=

array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

So I have implemented a piece of code that goes do the job:

b = [[100, 101],[102, 103]]

for i in range(len(rows_to_keep)):
    a[i,columns_to_keep] = b[i]

Al thought the previous lines do the job I am wondering how to do it slicing and in a faster fashion. Also in a way that with:

columns_to_keep = [0,2] 
rows_to_keep = [0,2]

the desired output is

array([[100, 1, 101],
       [3, 4, 5],
       [102, 7, 103]]).

Many thanks!


回答1:


Indexing with lists like [1,2] is called advanced indexing. By itself it produces a copy, not a view. You have to use one indexing expression, not two to assign or change values. That is a[[1,2],:] is a copy, a[[1,2],:][:,[1,2]] += 100 modifies that copy, not the original a.

In [68]: arr = np.arange(12).reshape(3,4)

Indexing with slices; this is basic indexing:

In [69]: arr[1:,2:]
Out[69]: 
array([[ 6,  7],
       [10, 11]])

In [70]: arr[1:,2:] += 100

In [71]: arr
Out[71]: 
array([[  0,   1,   2,   3],
       [  4,   5, 106, 107],
       [  8,   9, 110, 111]])

Doing the same indexing with lists requires arrays that 'broadcast' against each other. ix_ is a handy way of generating these:

In [73]: arr[np.ix_([1,2],[2,3])]
Out[73]: 
array([[106, 107],
       [110, 111]])

In [74]: arr[np.ix_([1,2],[2,3])] -= 100

In [75]: arr
Out[75]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Here's what ix_ produces - a tuple of arrays, one is (2,1) in shape, the other (1,2). Together they index a (2,2) block:

In [76]: np.ix_([1,2],[2,3])
Out[76]: 
(array([[1],
        [2]]), array([[2, 3]]))



回答2:


For the continuous rows and columns case, you can use basic slicing like this:

In [634]: a
Out[634]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

In [635]: b = np.asarray([[100, 101],[102, 103]])

In [636]: a[:rows_to_keep[1]+1, columns_to_keep[0]:] = b

In [637]: a
Out[637]: 
array([[  0, 100, 101],
       [  3, 102, 103],
       [  6,   7,   8]])



来源:https://stackoverflow.com/questions/48464015/writting-in-sub-ndarray-of-a-ndarray-in-the-most-pythonian-way-python-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!