问题
I am trying to draw a "one" on a numpy array np.zeros((28, 28)) by assigning certain rows and columns to 255. I have written the following code:
one = np.zeros((28, 28))
one[12:15][5:23] = 255
The output I'm getting after this is a simple array of zeros with no changes. Can anyone please explain this strange behavior?
Bonus
If you interchange [12:15] and [5:23], rows 17 to 19 are filled with 255.
回答1:
The notation you are using is valid but does something very different from what you expect. Numpy indices consist of tuples, one element per dimension. The index you are trying to get looks like this
one[(12:15, 5:23)] = 255
For convenience, python allows you to remove the parentheses, so almost everyone would write
one[12:15, 5:23] = 255
It's useful to remember that that's just shorthand for a tuple containing slice objects, because sometimes you have to build it externally.
Let's look at what your original index actually does. Each bracket expression in python is a call to __getitem__ or __setitem__. Your index can be rewritten as
view = one[12:15] # __getitem__
view[5:23] = 255 # __setitem__
You are allowed to pass in a tuple that is shorter than the number of dimensions. In that case, the leading dimensions are indexed, and all the remaining dimensions are implicit grabbed in their entirety. What that means practically is that you are effectively doing
view = one[12:15, :]
view[5:23, :] = 255
view is a slice of rows 12-14, inclusive. It is a 3x28 array. In keeping with python convention, numpy allows you to assign to indices past the end of an array, silently doing nothing. view has only 3 rows, so assigning rows 5-22 does nothing.
Hopefully this makes the situation in your edit clear. If you grab rows 5-22, you get an 18x28 slice of ones, offset by 5 rows. This slice has rows 12-14, so you end up setting rows 12+5, 13+5 and 14+5 in the original array.
回答2:
With one[12:15][5:23] you first select rows from 12 to 15 (3 rows), then you select rows 5 to 23 from these 3 rows. These rows do not exists, then you do not update anything.
The syntax for updating rows 12 to 15 crossed with columns 5 to 23 is
one[12:15,5:23] = 255
回答3:
To expand on jpl's answer: your syntax would be correct if you were dealing with python's list data structure. But you are dealing with numpy's ndarray data structure so it is not and jpl syntax is correct.
来源:https://stackoverflow.com/questions/60918089/assigning-elements-in-a-numpy-array-of-zeros