force maximum and minimum value in an array (clip and optimization tests)

you have an multi-dimensional array (we test with 3D here, but it could be « nD »), and you don’t want value to be bigger than a maximum, or smaller than a minimum.
I found (and tested) 3 different ways using NumPy:

  1. np.choose (with a trick in building choice matrix)
  2. use indexing to change directly the value for the « bad » values
  3. numpy.clip() (yes, I’ve seen that it existed after finding the 2 previous)

so here is the Python code for testing the speed

import numpy as np
from time import time

t1=t2=t3=0
for i in range(100):
a=np.random.rand(1000,1000,10)
timeStart=time()
a1=np.choose((a<.25)+2*(a>.75),(a,.25,.75))
t1+=time()-timeStart
timeStart=time()
a2=a
a2[a<.25]=.25
a2[a>.75]=.75
t2+=time()-timeStart
timeStart=time()
a3=np.clip(a,.25,.75)
t3+=time()-timeStart
if not np.all(a1==a2) :
print "not egal!"
if not np.all(a1==a3) :
print "not egal!"

print "time 'choose'",t1,
print "time 'indexing'", t2
print "time np.clip",t3
clip_optimizer_tester

guess which one is the fastests ?

np.clip obviously! numpy is not programmed by dummies, but by clever guys 🙂

and the factor is good : np.clip takes 4.1s on my computer, indexing is nearly 4 times slower with 15.6s and np.choose is really slow with more than 28s. The ratio is about the same for 10 times smaller matrix.