Question

I am trying to find all the values from numpy record array no1 which are closest to values in rec array no2 (record arrays have different number of values)

Lets say no1 has fields:

('electrode', 'i4'), ('no_of_interest_time', 'i4'), ('time', 'f8')

where time is time of specific event and no_of_interest_time indexes events that should be analyzed separately. Each of the events is given such a number and multiple events may share the same number. electrode holds the index of an electrode in which event was recorded (location).

no2 has the same fields but holds different events.

For each event in recarray no2, I want to find closest event from recarray no1 of the same type (no_of_interest_time) and location (electrode).

The way I can solve it using for loops would look like this, but I am looking for much more elegant solution:

import numpy as np

i_recarr1 = np.argsort(recarray1, order=['electrode', 'no_of_interest_time', 'time'])
recarr1_sorted = recarray1[i_recarr1]

i_recarr2 = np.argsort(recarray2, order=['electrode', 'no_of_interest_time', 'time'])
recarr2_sorted = recarray2[i_recarr2]

closest_events = recarr2_sorted.copy()

for electr in np.unique(recarr2_sorted['electrode']):
    # use only this electrode
    recarr1_record = recarr1_sorted[recarr1_sorted['electrode'] == electr]
    recarr1_record = recarr2_sorted[recarr2_sorted['electrode'] == electr]

    for interest in np.unique(recarr2_record['no_of_interest_time']):
        # use only this time of interest
        recarr1_interest = recarr1_sorted[recarr1_record['no_of_interest_time'] == interest]
        recarr2_interest = recarr1_sorted[recarr1_record['no_of_interest_time'] == interest]

        for idx, event2 in np.enumerate(recarr2_interest['time']):
            # loop through every event to find neighbours
            selected_idx = (np.abs(recarr1_interest['time']-event2)).argmin()
            closest_events[(closest_events['electrode'] == electr) & 
                           (closest_events['no_of_interest_time']) == interest][idx] = recarr1_interest['time'][selected_idx]

inverse_i = np.argsort(i_recarr2)       
closest_events[inverse_i]

I will appreciate any advice. Thanks in advance!!

Was it helpful?

Solution

How about this:

closest_events = []
for t in no1:
    #sort
    i = np.argsort(np.abs(t['time']-no2['time']))
    # select only events with the same no_of_interest_time and electrode
    i = i[(no2['electrode']==t['electrode']) &
          (no2['no_of_interest_time']==t['no_of_interest_time'])]
    closest = i[0] if len(i)>0 else np.nan
    closest_events.append(closest)

The idea is that for each event in no1 you first calculate distances between this event and all events in no2. Next, you sort the distances from the shortest to longest and store the indices (i in the function). From i you select only the elements of specific type and location and finally you take first of the remaining indices (if the array is empty, return NaN).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top