H. Vabri
H. Vabri

Reputation: 314

Changing multiple Numpy array elements using slicing in Python

Say I have the numpy array arr_1 = np.arange(10) returning:

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

How do I change multiple elements to a certain value using slicing?

For example: changing the zeroth, first and second element that occur every five elements, starting from the first element, to 100. I want this:

array([0, 100, 100, 100, 4, 5, 100, 100, 100, 9])

I tried arr_1[1::[5, 6, 7]] = 100 but that doesn't work.

Upvotes: 3

Views: 1559

Answers (4)

Paul Panzer
Paul Panzer

Reputation: 53029

If your repeat offset divides the array length:

a.reshape((-1, 5))[:, 1:4] = 100

General case requires two lines:

a[: len(a) // 5 * 5].reshape((-1, 5))[:, 1:4] = 100
a[len(a) // 5 * 5 :][1:4] = 100    

How it works: Reshaping in the described way stacks consecutive stretches of the array in such a way that the target substretches are aligned and can therefore be addressed in one go using standard 2d indexing:

>>> a = np.arange(15)
>>> a.reshape((-1, 5))
array([[ 0,  1x,  2x,  3x,  4],
       [ 5,  6x,  7x,  8x,  9],
       [10, 11x, 12x, 13x, 14]])

Upvotes: 1

Geoffrey Anderson
Geoffrey Anderson

Reputation: 1564

You just need to wrap your list of indexes in np.array(list). You were very close to being correct:

In [2]: arr_1 = np.arange(10)

In [3]: arr_1[np.array([0,1,2,5,6,7])] = 100

In [4]: arr_1
Out[4]: array([100, 100, 100,   3,   4, 100, 100, 100,   8,   9])

I used hand coded values for the indexes, per your requirements. You can get the indexes in an automated way using some technique you like, like that shown by Divakar.

Upvotes: 0

Divakar
Divakar

Reputation: 221564

Here's one approach with masking -

a = np.arange(10)       # Input array
idx = np.array([0,1,2]) # Indices to be set
offset = 1              # Offset

a[np.in1d(np.mod(np.arange(a.size),5) , idx+offset)] = 100

Sample run with original sample -

In [849]: a = np.arange(10)       # Input array
     ...: idx = np.array([0,1,2]) # Indices to be set
     ...: offset = 1              # Offset
     ...: 
     ...: a[np.in1d(np.mod(np.arange(a.size),5) , idx+offset)] = 100
     ...: 

In [850]: a
Out[850]: array([  0, 100, 100, 100,   4,   5, 100, 100, 100,   9])

Sample run with non-sequential indices -

In [851]: a = np.arange(11)       # Input array
     ...: idx = np.array([0,2,3]) # Indices to be set
     ...: offset = 1              # Offset
     ...: 

In [852]: a[np.in1d(np.mod(np.arange(a.size),5) , idx+offset)] = 100

In [853]: a
Out[853]: array([  0, 100,   2, 100, 100,   5, 100,   7, 100, 100,  10])

Upvotes: 0

Alexandre Kempf
Alexandre Kempf

Reputation: 989

Here is another solution based on what you did :

arr_1 = np.arange(10)
arr_1[1::5] = 100
arr_1[2::5] = 100
arr_1[3::5] = 100

and it returns :

array([  0, 100, 100, 100,   4,   5, 100, 100, 100,   9])

Upvotes: 1

Related Questions