2

I am trying to work with two arrays in a certain way in python. Lets say

A = np.array([5, 10, 30, 50])
B = np.array([2, 3, 4, 5])

now I have a target array C = [2, 7, 15, 25, 40]. I want to find a output value (say Y) for each element in C (say x) with conditions:

  • If x < A[0] then Y = B[0]
  • If A[i] < x < 2*A[i] < A[i+1] or A[i] < x < A[i+1] < 2*A[i] then Y=x
  • If A[i] < 2*A[i] < x < A[i+1] then Y = B[i+1]
  • If x > A[end] then Y = x

i is the maximum possible index satisfying the conditions

So, output becomes Y = [2, 7, 15, 4, 40]

This is what I have currently

A = np.array([5, 10, 30, 50])
B = np.array([2, 3, 4, 5])
C = np.array([2, 7, 15, 25, 40])

diffA = np.diff(A)

diffIdx = np.squeeze(np.where(diffA > A[0:len(A)-1]+1e-6))

Y = np.array([])

for x in C:
  idx = np.searchsorted(A, x)
  if idx == 0:
    Y = np.append(Y, B[0])
  elif np.any(diffIdx==idx-1) & (x>2*A[idx-1]+1e-6):
    Y = np.append(Y, B[idx])
  else:
    Y = np.append(Y, x)

This seems to work, and IPython console %timeit shows it takes 24.7 ms, but I was wondering if there is a better or faster method of doing the same.

Srimaya P.
  • 90
  • 1
  • 8
  • 1
    faster or slower would really be dictated by the sizes of the arrays involved. How big are your real arrays? (If they are fairly small, you might be better of with old school python lists and iteration) – Paritosh Singh Jan 23 '20 at 07:37
  • @ParitoshSingh the array sizes are small but I'd still like to figure out if this can be done better. – Srimaya P. Jan 23 '20 at 08:28
  • I am not sure that I understand your conditions. For example, `A[i] < x < A[i+1]` can be true for multiple `i`'s, so for which one you set `Y = B[i+1]`? – Andreas K. Jan 23 '20 at 09:08
  • @AndreasK. I don't think that's possible. `A` is an ascending array, so any element of `C` can only lie between any 2 consecutive values in `A`. – Srimaya P. Jan 23 '20 at 11:00

1 Answers1

1

Check this question Most efficient way to map function over numpy array . You can create an array of indices np.arange(C.size), make a function with all the logic of combining A, B and C element getting them by index and depending on the size of your arrays choose the fastest method to apply the function.

Yann
  • 2,426
  • 1
  • 16
  • 33
  • I agree to this being the most sensible thing to do. I tried out the methods in the post mentioned, and the direct functional implementation is what works for my actual data. – Srimaya P. Jan 24 '20 at 06:39