Home > Software engineering >  How to fill numpy array of zeros with ones given index ranges/slices
How to fill numpy array of zeros with ones given index ranges/slices

Time:05-02

The question is closely related to two other questions referenced below. Although they could be adapted, I'm not sure they provide an optimal solution given this specific case.

Given a numpy array of zeros

arr = np.zeros([2, 5])

array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

Fill with zero based on another array of ranges (or list of tuples)

ranges_ones = np.array([[0,3], [1,4]])

Result

array([[1., 1., 1., 1., 0.],
       [0., 1., 1., 1., 1.]])

How to fill numpy array of zeros with ones given index ranges/slices?

Related questions:

  1. How to fill numpy array of zeros with ones given indices/coordinates
  • can be adapted if ranges are converted to exact coordinates
  1. Slicing numpy array with another array
  • can be adapted if solutions are generalised for more than 1 dimension. e.g. if reduceat could be used for multiple arrays of slices

CodePudding user response:

Using numpy broadcasting, you could create a boolean array that is True for the cell that you want to be 1, False otherwise. Since the first column of ranges_ones is the starting indices and the second is the ending indices, we could create an interval using &

idx = np.arange(arr.shape[1])
s = (idx >= ranges_ones[:, [0]]) 
e = (idx <= ranges_ones[:, [1]])
arr[s & e] = 1

Output:

>>> arr
array([[1., 1., 1., 1., 0.],
       [0., 1., 1., 1., 1.]])

CodePudding user response:

You can create slice objects based on your array of ranges. The result is different from your intended answer because when slicing the stop value of the range is not included, but it's easy to adjust this so the result is what you're looking for.

import numpy as np

arr = np.zeros([2, 5])

ranges_ones = np.array([[0,3], [1,4]])

for i, range in enumerate(ranges_ones):
    arr[i, slice(range[0], range[1])] = 1
    # arr[i, range[0]:range[1]] = 1 also works btw

print(arr) # [[1. 1. 1. 0. 0.] [0. 1. 1. 1. 0.]]

CodePudding user response:

A simple enumerate() call should do the trick:

import numpy as np

arr = np.zeros([2, 5])
ranges_ones = np.array([[0, 4], [1, 4]])

for i, (a, b) in enumerate(ranges_ones):
    arr[i, a: b] = 1
    
print(arr)

Output:

[[1. 1. 1. 1. 0.]
 [0. 1. 1. 1. 0.]]
  • Related