Mark
Mark

Reputation: 778

How can I replace 1s in a binary array with natural numbers, maintaining the position of 0s?

I'm using Numpy and SciPy. I have two arrays, the first of which is binary, the second a consecutive range of natural numbers from a to b e.g.

mask = np.array([1, 1, 1, 1, 0, 0, 1, 0]) # length of 8, with 5 ones and 3 zeros
vals = np.array([2, 3, 4, 5, 6, 7, 8, 9]) # length of 8, only first 5 values will be used in this case - corresponding to the 5 ones in the first array

I'd like to essentially replace the 1s in the first array with the values in the second (kept in order) e.g. the required result in this example scenario would be:

result = [2,3,4,5,0,0,6,0]

I've already tried different methods with NumPy masked arrays and the vectorise function. My current solution is below, but in order to maintain the state, I've had to introduce a global variable!

global count
count = 0
def func(a,b):
    global count
    if a ==1:
        return b - count
    else:
        count +=1
        return 0
v_func = np.vectorize(func)
result = v_func(mask, vals)
print result

Is there a more elegant way of doing this, (ideally using NumPy)?

(Side note, the real arrays I'm working with are very large and so my solution needs to be sensitive to the amount of memory consumed - obviously I can convert to sparse arrays, but I've still hit memory errors a couple of times trying to find different solutions.)

Upvotes: 1

Views: 286

Answers (2)

Rockybilly
Rockybilly

Reputation: 4520

Here is a one liner, though I must say it is not an optimized way and not very elegant. But you can examine it for practice purposes.

a = [1, 1, 1, 1, 0, 0, 1, 0]
b = [2, 3, 4, 5, 6, 7, 8, 9]

c = [b[sum(a[:i])] if a[i] else 0 for i in range(len(a))]
print c
# Gives [2, 3, 4, 5, 0, 0, 6, 0]

Upvotes: 2

Warren Weckesser
Warren Weckesser

Reputation: 114946

Here's one way:

In [15]: result = np.zeros_like(vals)

In [16]: result[mask > 0] = vals[:mask.sum()]

In [17]: result
Out[17]: array([2, 3, 4, 5, 0, 0, 6, 0])

Upvotes: 2

Related Questions