I am attempting to find the smallest n values in a list where their location is at least x apart, accounting for duplicates. e.g. smallest 5 values that are located at least 2 away from each other.
Straightforward example:
values = [-9995, -82, -659, -1006, -2009, 2062, -10107, -12, 13]
result: [-10107, -9995, -2009, -659, 13]
More complex example:
values = [-9995, -83, -82, -82, -1006, -2009, 18, 2062, -659 ,-9995, -9995]
For example in the above list:
- -9995 is the smallest value.
- -9995 occurs again and it is at least 2 apart from the first one. The remaining -9995 is ignored as it is only 1 apart from the previous one.
- -2009 is the third smallest value
- -1006 is not considered since it is only 1 apart from the previous values. So we take the next smallest value -659, as it is at least 2 away from previous values (assuming we take the first and last -9995 and ignore the second to last)
- -83 is not considered since it is only one away from -9995. so we take -82.
- we have reached 5 numbers so we stop
result: [-9995, -9995, -2009, -659, -82]
The lists I am working with are ~1,000,000 elements long, and I have ~1000 lists. I generated these lists from a pandas DataFrame (by iterating through groupby) so if there is a numpy/pandas approach to optimise this calculation it would be helpful.
Attempt so far is able to generate result assuming duplicates do not occur:
def smallest_values(list_of_numbers: list, n_many: int, x_apart: int):
sorted_values = sorted(values)
small_val, small_val_loc = [], []
for val in sorted_values:
if len(small_val) <= n_many:
ind = list_of_numbers.index(val)
within_x = [i for i in range(ind-(x_apart-1), ind+x_apart)]
if not any(i in small_val_loc for i in within_x):
small_val_loc.append(ind)
small_val.append(val)
return small_val
values_simple = [-9995, -82, -659, -1006, -2009, 2062, -10107, -12, 13]
values_complex = [-9995, -83, -82, -82, -1006, -2009, 18, 2062, -659 ,-9995, -9995]
d = 2
n = 5
smallest_values(values_simple, n, d) # [-10107, -9995, -2009, -659, 13] CORRECT
smallest_values(values_complex, n, d) # [-9995, -2009, -659, -82] INCORRECT