1

I am trying to iterate over numpy arrays and generate an output, which has conditions similar to that described below:

min1 = 3
max1 = 1
a1 = np.array([1, 2, 5, 3, 4])
a2 = np.array([5, 2, 6, 2, 1])
output = np.zeros(5)
for i in range(0, 5):
  if((a1[i] - a2[i]) > min1):
    output[i] = 3 * (a1[i] - a2[i])

  if((a1[i] - a2[i]) < max1):
    output = 5 * (a1[i] - a2[i])

I need to optimize the above code, so that I utilize the numpy functionalities as the best and also avoid using a loop. How should I do it?

2
  • Why you looping here ?? Commented Jul 6, 2017 at 6:03
  • Not sure why a perfectly functional edit by @Sanober got rejected. I just manually redid his work. Commented Jul 6, 2017 at 7:08

5 Answers 5

2

While functions like select and where can condense the code, I think it's a good idea to know how to do this with basic boolean masking. It's applicable in many cases, and nearly always as fast.

Calculate the difference which is used several times:

In [432]: diff = a1-a2
In [433]: diff
Out[433]: array([-4,  0, -1,  1,  3])
In [435]: output = np.zeros_like(a1)

find those cases where it meets the first condition, and set the corresponding elements of output:

In [436]: mask1 = diff>min1
In [437]: output[mask1] = 3*diff[mask1]

repeat for the second condtion:

In [438]: mask2 = diff<max1
In [439]: output[mask2] = 5*diff[mask2]

and again if there are more conditions.

In [440]: output
Out[440]: array([-20,   0,  -5,   0,   0])

In this example, only the -4 and -1 met condition 2, and none condition 1.

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

Comments

1

Welcome to SO! First, a tip for questions:

  1. Even your current loopy code doesn't work, as you're assigning values to output instead of output[i]. Try to make sure that if you're asking for a code refactor your original code works (and other than numpy tags, asking for code refactoring on SO will normally get you downvoted).

  2. You're going to want a nested np.where statement like this

    output = np.where((a1 - a2) > min1, 3 * (a1 - a2), (np.where((a1 - a2) < max1, 5 * (a1 - a2), 0)))
    

This way you don't need to initialize output, and no more loopy code.

If you have lots of conditions, you can also use np.select

d = a1 - a2
condlist = [d > min1, d < max1]
choicelist = [3 * d, 5 * d]
output = np.select(condlist, choicelist)

1 Comment

This works too! Thanks! And i'll keep the tips in mind!
0

Your question is a bit vague. Here's a possible solution depending on what you really want.

This solution will return 2 arrays of that contains values that belong to the min and max that you indicated. What this does is that it does the - operation to your two arrays then instead of doing if, numpy has the function called where that does this for you without iterating through the whole array.

import numpy as np
min1=3
max1=1
a1=np.array([1,2,5,3,4])
a2=np.array([5,2,6,2,1])
array_op = a1-a2
min_output = 3*(array_op[np.where((array_op)>min1)])
max_output = 5*(array_op[np.where((array_op)<max1)])

Comments

0

The solution is

    import numpy as np
    min1=3
    max1=1
    a1=np.array([1,2,5,3,4])
    a2=np.array([5,2,6,2,1])

    output=np.zeros(5)
    diff = a1-a2

    output[np.where(diff < max1)] = diff[np.where(diff < max1)]*5
    output[np.where(diff > min1)] = diff[np.where(diff > min1)]*3

Comments

-1

The operation a1[i]-a2[i] is done 4 times in a single iteration Save it as a variable to save 3*5 = 15 computations

1 Comment

If you don't have a complete answer, just leave a comment. You'll be able to comment once you get enough reputation.

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.