1

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

2 Answers 2

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]]))
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much!. 'a[np.ix_(rows_to_keep, columns_to_keep)] = b' it is the solution for me case.
0

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]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.