How to extract number of interest from an array while comparing it with a different array?

Viewed 70

I have the following two arrays:

array([154, 390, 635, 881], dtype=int64)

array([ 19,  25,  55,  95,  96, 100, 104, 125, 177, 191, 193, 209, 211,
        215, 217, 220, 260, 262, 264, 268, 299, 371, 418, 454, 457, 460,
        464, 467, 474, 476, 502, 504, 506, 511, 544, 615, 661, 707, 746,
        748, 752, 757, 787, 853, 855, 856, 906, 945, 989, 998], dtype=int64)

I want a code that will create a third array or list that will contain values from the second array that are the first number that is larger than the values of the first i.e. 177, 418, 661 and 906.

I tried the following code:

for i in range(len(xi)):
    newlist =[]
    for j in range(len(peaks)):
        if xi[i] > peaks[j] : newlist.append(xi[i])
        j=j+1

but the answer is [998, 998, 998, 998] which is the largest number of the second array

what i should change in order to have the desired values?

Thank you

4 Answers

We can use broadcasting to compare both arrays, and take the argmax along the second axis to find the indices of the first True values. Then index b with the resulting integer index array:

b[(b > a[:,None]).argmax(1)]
# array([177, 418, 661, 906])

Setup -

a = np.array([154, 390, 635, 881])

b = np.array([ 19,  25,  55,  95,  96, 100, 104, 125, 177, 191, 193, 209, 211,
        215, 217, 220, 260, 262, 264, 268, 299, 371, 418, 454, 457, 460,
        464, 467, 474, 476, 502, 504, 506, 511, 544, 615, 661, 707, 746,
        748, 752, 757, 787, 853, 855, 856, 906, 945, 989, 998])
a = [154, 390, 635, 881]

b = [ 19,  25,  55,  95,  96, 100, 104, 125, 177, 191, 193, 209, 211,
        215, 217, 220, 260, 262, 264, 268, 299, 371, 418, 454, 457, 460,
        464, 467, 474, 476, 502, 504, 506, 511, 544, 615, 661, 707, 746,
        748, 752, 757, 787, 853, 855, 856, 906, 945, 989, 998]

new = []
for n in a:
    for m in b:
        if m > n:
            new.append(m)
            break
print(new)

You need to break out of the second loop whenever you found the first number greater than the number you are comparing from the first array

This approach looks for the minimum value in the a2 array which is greater than each element in the a1 array; then appends each minimum value to a list of results.

Data:

a1 = np.array([154, 390, 635, 881)

a2 = np.array([19,  25,  55,  95,  96, 100, 104, 125, 177, 191, 193, 209, 211,
               215, 217, 220, 260, 262, 264, 268, 299, 371, 418, 454, 457, 460,
               464, 467, 474, 476, 502, 504, 506, 511, 544, 615, 661, 707, 746,
               748, 752, 757, 787, 853, 855, 856, 906, 945, 989, 998])

Sample Code:

l = []
for i in range(a1.size):
    l.append(a2[a2>a1[i]].min())

Output:

[177, 418, 661, 906]

As you're using numpy arrays, you can use numpy.searchsorted if array b is sorted

a = np.array([154, 390, 635, 881], dtype=int64)    
b = np.array([ 19,  25,  55,  95,  96, 100, 104, 125, 177, 191, 193, 209, 211,
        215, 217, 220, 260, 262, 264, 268, 299, 371, 418, 454, 457, 460,
        464, 467, 474, 476, 502, 504, 506, 511, 544, 615, 661, 707, 746,
        748, 752, 757, 787, 853, 855, 856, 906, 945, 989, 998], dtype=int64)

b[np.searchsorted(b,a, side='right')]

Output

array([177, 418, 661, 906])
  • to search for > use the argument side='right'
  • to search for >= use the argument side='left', which is the default behaviour.

Micro-Benchmark

Comparing searching with broadcasting and numpy.searchsorted

benchmark results

Code for the benchmark

def broadcast(n):
    b,a = n
    b.sort()
    return b[(b > a[:,None]).argmax(1)]
def searchsort(n):
    b,a = n
    b.sort()
    return b[np.searchsorted(b,a, side='right')]

import perfplot
perfplot.show(
    setup=lambda n: (np.random.randint(1, n, n), np.random.randint(1, n, n // 10)),
    n_range=[2 ** k for k in range(5,18)],
    kernels=[broadcast, searchsort],
    xlabel="len(x)",
)
Related