Быстрое чередование числовых массивов с числовым сравнением - PullRequest
0 голосов
/ 06 июля 2018

У меня есть 2 списка Python целых чисел. Списки возможно разных размеров. Один - это список индексов всех максимумов в наборе данных, а другой - список индексов всех минимумов. Я хочу составить список последовательных максимумов и минут по порядку и пропустить случаи, когда, скажем, 2 минуты находятся между 2 максимумами.

Скорость важнее всего, поэтому я спрашиваю, как можно сделать следующее быстрее (используя Numpy, я полагаю, а-ля этот ответ ): какой код numy может составить some_function() ниже, чтобы сделать этот расчет?

>>> min_idx = [1,5,7]
>>> max_idx = [2,4,6,8]
>>> some_function(min_idx, max_idx)
[1, 2, 5, 6, 7, 8]

В приведенном выше примере мы посмотрели, какой список *_idx начинается с более низкого значения, и выбрали его как «первое» (min_idx). Оттуда мы прыгаем вперед и назад между min_idx и max_idx, чтобы выбрать «следующее по величине число»:

  1. Начните с 1 из min_idx
  2. Посмотрите на max_idx, чтобы найти первое неиспользуемое число, которое больше 1: 2
  3. Вернитесь к min_idx, чтобы найти первое неиспользуемое число больше 2: 5
  4. Опять же для max_idx: мы пропустили 4, потому что меньше 5 и выбрали 6
  5. продолжать процесс, пока у нас не закончатся значения в любом списке.

В качестве другого примера, для min_idx = [1,3,5,7,21] и max_idx = [4,6,8,50] ожидаемый результат будет [1,4,5,6,7,8,21,50]

Мое текущее решение, отличное от Numpy, выглядит так, где idx - это вывод:

# Ensure we use alternating mins and maxes
idx = []
max_bookmark = 0
if min_idx[0] < max_idx[0]:
    first_idx = min_idx
    second_idx = max_idx
else:
    first_idx = max_idx
    second_idx = min_idx
for i, v in enumerate(first_idx):
    if not idx:
        # We just started, so put our 1st value in idx
        idx.append(v)
    elif v > idx[-1]:
        idx.append(v)
    else:
        # Go on to next value in first_idx until we're bigger than the last (max) value
        continue

    # We just added a value from first_idx, so now look for one from second_idx
    for j, k in enumerate(second_idx[max_bookmark:]):
        if k > v:
            idx.append(k)
            max_bookmark += j + 1
            break

В отличие от других ответов о слиянии массивов Numpy, здесь сложность заключается в сравнении значений элементов в виде одного прыжка между двумя списками на этом пути.

Фон: Мин. / Макс. Список

2 входных списка для моей задачи выше генерируются scipy.argrelextrema, который должен использоваться дважды: один раз, чтобы получить индексы максимумов, и снова, чтобы получить индексы минимумов. В конечном счете, я просто хочу один список индексов чередующихся максимумов и минут, поэтому, если есть какая-то функция scipy или numpy, которая может найти максимумы и минут набора данных и вернуть список индексов, указывающих чередующиеся максимумы и минуты , это решило бы то, что я ищу тоже.

1 Ответ

0 голосов
/ 06 июля 2018

Вот гораздо более простая логика без использования Numpy (примечание: предполагается, что max(min_idx) < max(max_idx):

min_idx = [1,3,5,7,21]
max_idx = [4,6,8,50]
res = []

for i in min_idx:
    if not res or i > res[-1]:
        pair = min([m for m in max_idx if m > i])
        res.extend([i, pair])

print(res)
>>> [1, 4, 5, 6, 7, 8, 21, 50]
...