0

I've been trying to do the following as a batch operation in numpy or torch (no looping). Is this possible?

Suppose I have:

indices: [[3],[2]] (2x1)

output: [[0,0,0,0,1], [0,0,0,1,1]] (2xfixed_num) where fixed_num is 5 here

Essentially, I want to make indices up to that index value 0 and the rest 1 for each element.

MLGOD
  • 1
  • 1
  • Can you give a specific example? – Ari K Jul 28 '20 at 20:24
  • yeah sure, what do you mean by example? I've provided one in the question? Here you can see that up to index 3 is 0 for first element and up to index 2 is 0 for second element as provided by indices array – MLGOD Jul 28 '20 at 20:28
  • Gotcha. I understand now. Let me try to come up with something non looping – Ari K Jul 28 '20 at 20:31

1 Answers1

0

Ok, so I actually assume this is some sort of HW assignment - but maybe it's not, either way it was fun to do, here's a solution for your specific example, maybe you can generalize it to any shape array:

def fill_ones(arr, idxs):
    x = np.where(np.arange(arr.shape[1]) <= idxs[0], 0, 1) # This is the important logic.
    y = np.where(np.arange(arr.shape[1]) <= idxs[1], 0, 1)
    return np.array([x, y])

So where the comment is located - we use a condition to assign 0 to all indices before some index value, and 1 after such value. This actually creates a new array as opposed to a mask that we can use to the original array - so maybe it's "dirtier".

Also, I suspect it's possible to generalize to arrays more than 2 dimensions, but the solution i'm imagining now uses a for-loop. Hope this helps!

Note: arr is just a numpy array of whatever shape you want the output to be and idxs is a tuple of what indices past you want to the array elements to turn into 1's - hope that is clear

Ari K
  • 434
  • 2
  • 18
  • thanks for this! but, the way you've done it is elem by elem, which would require a loop anyways right for larger number of elements? I was trying to find a way without having to do each one individually. – MLGOD Jul 28 '20 at 21:09
  • Is it elem by elem? I was under the impression the np methods didn't loop but did things via vectorization – Ari K Jul 28 '20 at 21:11
  • See: https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.where.html#numpy.where and https://medium.com/@emayoung95/using-numpy-where-function-to-replace-for-loops-with-if-else-statements-a1e6044ac4c1 . np.where is way faster than a traditional for-loop – Ari K Jul 28 '20 at 21:15
  • Not element by element, but it is index by index (as in first (3) then (2) (per your example)). I'm under the impression that np.where method doesn't loop but does things via vectorization – Ari K Jul 28 '20 at 21:17
  • here you have to call np.where once for each index value right? Right by elem, i might for each index – MLGOD Jul 28 '20 at 21:18
  • Yeah - I assumed you wanted to avoid looping over the elements in the array, not the elements in the index – Ari K Jul 28 '20 at 21:20
  • The latter is probably possible, just requires extra digging into the np methods (maybe the np.where mask examples) – Ari K Jul 28 '20 at 21:21
  • check np.mgrid for a multidimensional version of np.arange. It's not exactly the same but can be used like that https://stackoverflow.com/questions/32208359/is-there-a-multi-dimensional-version-of-arange-linspace-in-numpy – Ari K Jul 28 '20 at 21:24
  • yeah. actually was just told about a way to do this -- generate all possible cases using upper triangular matrix and just index from that – MLGOD Jul 28 '20 at 21:24
  • cool - not sure how that plays into this but glad you got a solution – Ari K Jul 28 '20 at 21:25
  • def foo(length, indices): mask = torch.triu(torch.ones((length+1,length+1), dtype=torch.int))[1:,:-1] return mask[indices] if you're interested – MLGOD Jul 28 '20 at 21:26