Home > OS >  find max value in islands defined by other vector
find max value in islands defined by other vector

Time:12-01

I have a vector of values vals, a same-dimension vector of frequencies freqs, and a set of frequency values pins.

I need to find the max values of vals within the corresponding interval around each pin (from pin-1 to pin 1). However, the intervals merge if they overlap (e.g., [1,2] and [0.5,1.5] become [0.5,2]).

I have a code that (I think) works, but I feel is not optimal at all:

import numpy as np

np.random.seed(666)
freqs = np.linspace(0, 20, 50)
vals = np.random.randint(100, size=(len(freqs), 1)).flatten()
print(freqs)
print(vals)

pins = [2, 6, 10, 11, 15, 15.2]
# find one interval for every pin and then sum to find final ones
islands = np.zeros((len(freqs), 1)).flatten()
for pin in pins:
    island = np.zeros((len(freqs), 1)).flatten()
    island[(freqs >= pin-1) * (freqs <= pin 1)] = 1
    islands  = island
islands = np.array([1 if x>0 else 0 for x in islands])
print(islands)

maxs = []
k = 0
idxs = []
for i,x in enumerate(islands):
    if (x > 0) and (k == 0):  # island begins
        k  = 1
        idxs.append(i)
    elif (x > 0) and (k > 0):  # island continues
        pass
    elif (x == 0) and (k > 0):  # island finishes
        idxs.append(i)
        maxs.append(np.max(vals[idxs[0]:idxs[1]]))
        k = 0
        idxs = []
        continue
print(maxs)
    

Which gives maxs=[73, 97, 79, 77].

CodePudding user response:

Here's some optimizations for your code. There are many numpy functions that make your life easier, get to know them and use them ;). I tried commenting my code to make it as understandable as possible, but let me know if anything is unclear!

import numpy as np

np.random.seed(666)
freqs = np.linspace(0, 20, 50)
vals = np.random.randint(100, size=(len(freqs), 1)).flatten()
print(freqs)
print(vals)

pins = [2, 6, 10, 11, 15, 15.2]
# find one interval for every pin and then sum to find final ones

islands = np.zeros_like(freqs) # in stead of:   np.zeros((len(freqs), 1)).flatten()

for pin in pins:
    island = np.zeros_like(freqs) # see above comment
    island[(freqs >= pin-1) & (freqs <= pin 1)] = 1 # "&" makes it more readable
    islands  = island

# in stead of np.array([1 if x>0 else 0 for x in islands])
islands = np.where(islands > 0, 1, 0)  # read as: where  "islands > 0" put a '1', else put a '0'


# compare each value with the next to get island/sea transistions (islands are 1's seas are 0's)
island_edges = islands[:-1] != islands[1:]

# split at the edges ( 1 to account for starting at the 1 index with comparisons
# islands_and_seas is a list of 'seas' and 'islands'
islands_and_seas = np.split(islands, np.where(island_edges)[0] 1)

# do the same as above but on the 'vals' array
islands_and_seas_vals = np.split(vals, np.where(island_edges)[0] 1)

# get the max values for the seas and islands
max_vals = np.array([np.max(arr) for arr in islands_and_seas_vals])

# create an array where the islands -> True, and seas -> False
islands_and_seas_bool = [np.all(arr) for arr in islands_and_seas]

# select only the max values of islands with
maxs = max_vals[islands_and_seas_bool]

print(maxs)
  • Related