W.Ellis
W.Ellis

Reputation: 37

Apply different functions to an array depending on the value

I'm attempting to apply a different function to the first and second part of a numpy array. So in this example, multiplying the terms less than 0.5 by 2 and adding 1 to the terms of 0.5 and above.

def myFunc:
    x = numpy.linspace(0,1,11)
    def test():
        for i in x:
            if i < 0.5:
                a = i*2
            else:
                a = i+1.0
        return(a)

print(test())

Which I want to return:

[0,0.2,0.4,0.6,0.8,1.5,1.6,1.7,1.8,1.9,2]

Thank You.

Upvotes: 1

Views: 674

Answers (4)

JE_Muc
JE_Muc

Reputation: 5774

This should do it:

x[x < 0.5] *= 2
x[x >= 0.5] +=1

If you want to stick with numpy, this is highly preferable over list comprehensions.

Here is a short comparison using list comprehension and numpy masking:

def myFunc_lc(x):
    return np.asarray([i*2 if i < 0.5 else i+1 for i in x])

def myFunc_np(x):
    x[x < 0.5] *= 2
    x[x >= 0.5] +=1
    return x

def myFunc_np2(x):  # using a constant masking array
    ma = x < 0.5
    x[ma] *= 2
    x[~ma] +=1
    return x

x = np.linspace(0, 1, 11)
%timeit myFunc_np(x)  # 6.62 µs ± 160 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit myFunc_np2(x)  # 6.24 µs ± 113 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit myFunc_lc(x)  # 6.75 µs ± 160 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit np.select([x<0.5,x>=0.5],[x*2,x+1])  # 39.9 µs ± 1.78 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

x = np.linspace(0, 1, 10000)
%timeit myFunc_np(x)  # 43.4 µs ± 1.13 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit myFunc_np2(x)  # 43.8 µs ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit myFunc_lc(x)  # 3.7 ms ± 103 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit np.select([x<0.5,x>=0.5],[x*2,x+1])  # 79.2 µs ± 2.54 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

I guess it is quite obvious why numpy masking is better than list comprehension. Especially when using larger arrays, numpy is alot faster. Using small arrays, numpy is only slightly faster. np.select is really slow for short arrays but quite ok for larger arrays. Creating a mask in myFunc_np2 is even faster for small arrays, but slightly slower for larger arrays.

Upvotes: 0

BENY
BENY

Reputation: 323266

If you want a numpy solution , I will using select

np.select([x<0.5,x>=0.5],[x*2,x+1])
Out[905]: array([0. , 0.2, 0.4, 0.6, 0.8, 1.5, 1.6, 1.7, 1.8, 1.9, 2. ])

Upvotes: 1

Ken T
Ken T

Reputation: 2553

x = np.linspace(0,1,11)
x[x<0.5]*=2
x[x>=0.5]+=1

Upvotes: 2

user3483203
user3483203

Reputation: 51155

You could simply use a list comprehension:

[i*2 if i < 0.5 else i+1 for i in x]

Upvotes: 1

Related Questions