-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: advanced slicing (on left hand side) #15318
Comments
Masked arrays or advanced indexing in general can help you do this. To be honest, I am a bit cautious about such an addition. I admit, it is probably fairly straight forward in a sense, but it also seems to introduce a hole new complexity to indexing (which already is complicated enough that most users do not really know the full power of advanced indexing). I see two main possibilities:
Of course I am handwaving a bit here, your approach can obviously be better optimized, and there will be some in-between use cases where that may be more substantial. The main question is whether the use-case (and common of use) is worth the additional complexity (both in code and teaching users). Another alternative could be to not do this within indexing, but rather its own function, although it may not change things much. Could you write more about your use-case, and maybe float this idea to the mailing list, since it is a fair big API change proposal it needs to go there anyway. Once there is some agreement that this should be tried, someone will have to pick it up and try to create a PR for it. |
Thanks for the reply, I'll definitely think about the use case of this more and probably send something to the mailing list later! Another thing, actually I believe advanced indexing won't help in this case: The height/width of different rectangles are different. Therefore, those advanced indices cannot broadcast together due to different length. I'm not sure is there any way to generate the indices using less than This is the most efficient code I've came up with (draw 20 rectangles): import numpy as np
xy = np.random.randint(0, 256, (20,2,2), 'B')
xy.sort(2)
c = np.random.randint(0, 256, (20,3), 'B')
a = np.zeros((256,256,3), 'B')
vindex = np.concatenate([np.broadcast_to(np.arange(i,j,1,'B')[:,None],(j-i,J-I))for (i,j),(I,J) in xy],None)
hindex = np.concatenate([np.broadcast_to(np.arange(I,J,1,'B') ,(j-i,J-I))for (i,j),(I,J) in xy],None)
a[vindex,hindex] = c.repeat((xy[...,1]-xy[...,0]).prod(1,'H'), 0) Essentially it still uses python loop of size I also implemented a tricky solution using masked array: # xy and c same as above
N = np.arange(0, 256, 1, 'B')[:,None]
a = np.zeros((256,256,3), 'B')
m = (xy[:,1,0]>N) | (N>=xy[:,1,1]) | ((xy[:,0,0]>N) | (N>=xy[:,0,1]))[:,None]
A,m = np.broadcast_arrays(a[:,:,None], m[...,None])
A = np.ma.masked_array(A, m, hard_mask=True)
A[:] = c This is fully vectorized without python loop, but creating such "broadcasted mask" is very memory costly |
Yeah, you will have to repeat Of course, I am sure it could be a small factor faster, but note that:
is almost 5 times as fast as your function for that example (although all the cast to 'B' will be counterproductive for speed at least unless the arrays are large enough for memory to take an effect, maybe even then.) There is always the possibility of writing something like this yourself. E.g. cython is probably pretty nice to do. |
One thing that might be neat is allowing some kind of hook for slice objects, such that Probably something we should not think about before nailing down the |
Introduction
numpy
is an important tool in scientific computation (e.g. optimization), and visualization is an important subject in this field. Sometimes, after done some numerical optimization, people would want to visualize the result of how things get optimized. In order to do so, a common way is to draw some raw video (by manipulating array) and play that later using tools such asffmpeg
.With advanced indexing, point drawing can be extremely simple, but line/box drawing is getting inconvenient. What people usually have is indexes of start/end point. Since they can't put the indexes in slice, neither can they unite the tiny slices to a big slice, they have to explicitly draw using (nested) for loop + tiny-slice assigning. This is not taking advantage of
numpy
's vectorization, and is slow due to huge python overhead.Definition
One way to solve this is allowing advanced slicing (i.e. slice array using array). A straightforward example would be
The problem is, when applied on RHS, advanced slicing have to generate a "physical" array, which might make the result non-rectangular and unsupported by
numpy
.On the contrary, indexing on LHS is fully "imaginary". Therefore, advanced slicing becomes possible:
Since this makes
ndarray
much more powerful, I would strongly request such an enhancement. There are two set of detailed rules on my mind:Possible Rule 1
Possible Rule 2
?
, which is only broadcastable against shape1
.Example
Draw 10 random rectangles on a 256x256 black area with random grayscale
Given info of 10 rectangles in 1000 frames, and color of each rectangle, draw them into a raw video of 256x256
Compared to the current implementation
Things other than assigning. This might be more tricky because it cannot be translated to
a[xs:ys] = a[xs:ys] * b
Note
Another way to solve non-rectangular broadcast assigning problem is using a masked-array. But generating such a mask is inefficient, and sometimes non-trivial. It might take huge memory (and long time) to generate the mask in the first place
The text was updated successfully, but these errors were encountered: