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:
- can be adapted if ranges are converted to exact coordinates
- 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.]]