0

Consider an list of numpy arrays with values either -1’s or 1’s allocated in random positions.

a = np.array([1,-1,1,1,-1,1,-1,-1,1,-1])
b = np.array([-1,-1,1,-1,1,1,-1,1,-1,-1])

I need to perform operations on these arrays like sum and point wise multiplication.

For example, after summing 2 arrays i will have a new one with values -2,0 and 2.

c = a + b
c = [ 0 -2 2 0 0 2 -2 0 0 -2]

Now i would like to “normalize” it back to -1’s and 1’s.

For the 2’s and -2’s it is easy:

c[c < 0] = -1

c[c > 0] = 1

The problem is the 0. For them i would like to randomly choose either a -1 or a 1.

The desired output would be like:

c =  [ 1 -1 1 -1 -1 1 -1 1 -1 -1]

In generalized terms my question is how to find all N values equal to x, in an array, then substitute each for a random number.

My question is how to do this in the most “pythonic”, and fastest, way?

Thank’s

2
  • 2
    Please give an example of input arrays, the intermediate step and the expected output. Commented Jan 26, 2020 at 0:08
  • 1
    Hey! Thanks. I tried to put an example of the problem! Commented Jan 26, 2020 at 0:29

3 Answers 3

1

Just Posting the final results from the answers i got so far. If anyone in the future has a better solution please share it!

I timed the 3 solutions i found and one i did.

def Norm1(HV):
    HV[HV > 0] = 1
    HV[HV < 0] = -1
    zind = np.where(HV == 0)[0]
    HV[zind] = np.array([np.random.choice([1, -1]) for _ in zind])
    return HV

def norm2(HV):
    if HV == 0: 
        return np.random.choice(np.array([-1,1])) 
    else: 
        return HV / HV * np.sign(HV)                                                                         

Norm2 = np.vectorize(norm2)

def Norm3(HV):
    HV[HV > 0] = 1
    HV[HV < 0] = -1
    mask = HV==0;
    HV[mask] = np.random.choice((-1,1),HV[mask].shape)
    return HV

def generate(size):
    return np.random.binomial(1, 0.5, size=size) * 2 - 1

def Norm4(arr):
    np.floor_divide(arr, 2, out=arr)
    positions = (arr == 0)
    size = sum(positions)
    np.add.at(arr, positions, generate(size)

The timings were:

%%timeit
d = Norm1(c)
203 µs ± 5.9 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
d = Norm2(c)
33.4 ms ± 1.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
d = Norm3(c)
217 µs ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
d = Norm4(c)
21 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

So as it stands it looks like answer 1 and 3 are the best ones. The difference between them looks minimal, but after trying some more runs the number 1 always come slightly on top.

Thanks for the Helps guys! I will add some references to HD computing in the question as this is a core problem in this application so it will be easier for someone to find it if needed.

Sign up to request clarification or add additional context in comments.

Comments

0

I'm not in any way claiming this is the fastest nor most efficient approach.

c = np.array([ 0, -2, 2, 0, 0, 2, -2, 0, 0, -2])                       

def norm(a): 
    if a == 0: 
        return np.random.choice(np.array([-1,1])) 
    else: 
        return a / a * np.sign(a)                                                                         

v_norm = np.vectorize(norm)
norm_arr = v_norm(c)                                   

Result:

In [64]: norm_arr                                                             
Out[64]: array([ 1, -1,  1,  1, -1,  1, -1,  1, -1, -1])

2 Comments

Hello! Thanks for the idea! I will try this one an compare the performance of it against other solutions.
Ok, you're welcome. Please post an answer with your timing results when you're done!
0

You might use:

>>> c = [0, -2, 2, 0, 0, 2, -2, 0, 0, -2]
>>> c = np.array([0, -2, 2, 0, 0, 2, -2, 0, 0, -2])
>>> zind = np.where(c==0)[0]
>>> c[zind] = np.array([np.random.choice([1, -1]) for _ in zind])
>>> c
array([ 1, -2,  2, -1, -1,  2, -2, -1,  1, -2])

2 Comments

mask = c==0; a[mask] = np.random.choice((-1,1),a[mask].shape)
It looks like this one might be really fast! Thanks! Will try it against other ideas to see how each runs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.