Хранение данных для облегчения интерполяции данных в Python - PullRequest
6 голосов
/ 24 мая 2009

У меня более 20 таблиц, похожих на таблицу 1. Где все буквы представляют фактические значения.

Table 1:
$ / cars |<1 | 2 | 3 | 4+
<10,000  | a | b | c | d
20,000   | e | f | g | h
30,000   | i | j | k | l
40,000+  | m | n | o | p

Пользовательский ввод может быть, например, (2.4, 24594), который является значением между f, g, j и k. Мое определение функции Python и псевдокод для вычисления этой билинейной интерполяции выглядит следующим образом.

def bilinear_interpolation( x_in, y_in, x_high, x_low, y_low, y_high ):
   # interpolate with respect to x
   # interpolate with respect to y
   # return result

Как мне хранить данные из таблицы 1 (файл, раздел, кортеж или набор списков), чтобы я мог выполнять билинейную интерполяцию наиболее эффективно и правильно?

Ответы [ 3 ]

7 голосов
/ 24 мая 2009

Если вам нужно наиболее эффективное в вычислительном отношении решение, которое я могу придумать и не ограниченное стандартной библиотекой, то я бы порекомендовал scipy / numpy. Сначала сохраните массив a..p в виде двумерного массива numpy, а затем массивы $ 4k-10k и 1-4 как одномерные массивы 1D. Используйте scipy interpolate.interp1d, если оба одномерных массива монотонно растут, или interpolate.bsplrep (двумерное представление сплайнов), если нет, и ваши примерные массивы такие же маленькие, как ваш пример. Или просто напиши свое собственное и не заморачивайся со Сципи. Вот несколько примеров:

# this follows your pseudocode most closely, but it is *not*
# the most efficient since it creates the interpolation 
# functions on each call to bilinterp
from scipy import interpolate
import numpy
data = numpy.arange(0., 16.).reshape((4,4))  #2D array
prices = numpy.arange(10000., 50000., 10000.)
cars = numpy.arange(1., 5.)
def bilinterp(price,car):
    return interpolate.interp1d(cars, interpolate.interp1d(prices, a)(price))(car)
print bilinterp(22000,2)

В последний раз, когда я проверял (версия scipy от 2007-го), он работал только для монотонно увеличивающихся массивов x и y)

для небольших массивов, таких как этот массив 4x4, я думаю, вы хотите использовать это: http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.bisplrep.html#scipy.interpolate.bisplrep которая будет обрабатывать более интересные формы поверхностей, и функцию нужно будет создать только один раз. Для больших массивов, я думаю, вы хотите это (не уверен, что это имеет те же ограничения, что и interp1d): http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp2d.html#scipy.interpolate.interp2d но они оба требуют другой и более подробной структуры данных, чем три массива в приведенном выше примере.

3 голосов
/ 24 мая 2009

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

0 голосов
/ 24 мая 2009

Нет ничего особенного в билинейной интерполяции, которая делает ваш случай использования особенно странным; вам просто нужно сделать два поиска (для блоков хранения полных строк / столбцов) или четыре поиска (для хранения типа массива). Наиболее эффективный метод зависит от ваших шаблонов доступа и структуры данных.

Если ваш пример действительно представительный, с 16 записями, вы можете сохранить его как угодно, и он будет достаточно быстрым для любых нормальных нагрузок.

...