2016-08-11 3 views
2

Я пишу сплайновый класс в Python. Для вычисления интерполированного значения сплайна требуется индекс ближайших точек данных x. В настоящее время упрощенная версия выглядит следующим образом:Эффективный способ поиска индекса интервала

def evaluate(x): 
    for ii in range(N): # N = len(x_data) 
     if x_data[ii] <= x <= x_data[ii+1]: 
      return calc(x,ii) 

Так перебирает список x_data точек, пока он не найдет более низкий индекс ii интервала, в которых x ложь и использует в функции calc, которая выполняет сплайн-интерполяции , В то время как функциональный, похоже, что это было бы неэффективно для больших массивов x_data, если x близко к концу набора данных. Есть ли более эффективный или элегантный способ выполнения той же функциональности, которая не требует, чтобы каждый интервал был проверен итеративно?

Примечание: x_data можно считать сортированным таким образом x_data[ii] < x_data[ii+1], но не обязательно равномерно распределенным.

ответ

4

это именно то, что разрез`ать для https://docs.python.org/2/library/bisect.html

from bisect import bisect 
index = bisect(x_data,x) 
#I dont think you actually need the value of the 2 closest but if you do here it is 
point_less = x_data[index-1] # note this will break if its index 0 so you probably want a special case for that 
point_more = x_data[index] 

closest_value = min([point_less,point_more],key=lambda y:abs(x-y)) 

в качестве альтернативы следует использовать бинарный поиск (на самом деле им очень уверен, что тот, что Bisect использует под капотом) .... это должно быть худший случай O(log n) (если ваш входной массив уже отсортирован)

+2

Это заказ O (log n), фактически. И я просто посмотрел на исходный код для 'bisect()': это двоичный поиск. –

+1

Я не думаю, что это работает. 'bisect ([0,1,2], 0,1])' дает 1, а не 0, поэтому сравнение значений в 'index' и' index + 1' будет смотреть на '[1,2]', а не '[ 0,1] '. – DSM

+0

@DSM, потому что bisect ищет точку вставки для x, так что x_data остается в отсортированном порядке, просто вычтите 1 для результата и исправьте негативы, и это должно сделать трюк – Copperfield

Смежные вопросы