Минимальное расстояние для каждого значения в массиве относительно другого - PullRequest
4 голосов
/ 07 мая 2019

У меня есть два целых массива целых чисел A и B. Значения в массиве A и B соответствуют моментам времени, в которые происходили события A и B. Я хотел бы преобразовать A так, чтобы он содержал время с момента последнего события b.

Я знаю, что мне нужно вычесть каждый элемент A на его ближайший меньший элемент B, но я не уверен, как это сделать. Любая помощь будет принята с благодарностью.

>>> import numpy as np

>>> A = np.array([11, 12, 13, 17, 20, 22, 33, 34])
>>> B = np.array([5, 10, 15, 20, 25, 30])

Желаемый результат:

cond_a = relative_timestamp(to_transform=A, reference=B)
cond_a
>>> array([1, 2, 3, 2, 0, 2, 3, 4])

Ответы [ 3 ]

2 голосов
/ 07 мая 2019

Вы можете использовать np.searchsorted , чтобы найти индексы, где элементы A должны быть вставлены в B для поддержания порядка. Другими словами, вы находите ближайший элемент в B для каждого элемента в A:

idx = np.searchsorted(B, A, side='right')
result = A-B[idx-1] # substract one for proper index

Согласно поисковому запросу docs используется двоичный поиск , поэтому он будет хорошо масштабироваться для больших входных данных.

1 голос
/ 07 мая 2019

Вот подход, заключающийся в вычислении парных разностей.Обратите внимание, что он имеет сложность O(n**2), поэтому для больших массивов ответ @ brenlla будет работать намного лучше.

Идея состоит в том, чтобы использовать np.subtract.outer, а затем найти минимальную разницувдоль оси 1 над masked array, где рассматриваются только значения в B, меньшие a:

dif = np.abs(np.subtract.outer(A,B))
np.ma.array(dif, mask = A[:,None] < B).min(1).data
# array([1, 2, 3, 2, 0, 2, 3, 4])
0 голосов
/ 07 мая 2019

Поскольку я не уверен, если действительно быстрее вычислить все попарные разности, вместо цикла питона для каждой записи массива (наихудший случай O (Len (A) + len (B)), решение с циклом :

A = np.array([11, 12, 13, 17, 20, 22, 33, 34])
B = np.array([5, 10, 15, 20, 25, 30])

def calculate_next_distance(to_transform, reference):
    max_reference = len(reference) - 1
    current_reference = 0
    transformed_values = np.zeros_like(to_transform)
    for i, value in enumerate(to_transform):
        while current_reference < max_reference and reference[current_reference+1] <= value:
            current_reference += 1
        transformed_values[i] = value - reference[current_reference]
    return transformed_values

calculate_next_distance(A,B)
# array([1, 2, 3, 2, 0, 2, 3, 4])
...