简化Python中数据插值的数据存储

6 投票
3 回答
1865 浏览
提问于 2025-04-15 11:48

我有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 个回答

0

双线性插值并没有什么特别之处,也并不是说你的使用情况很奇怪;你只需要进行两次查找(对于完整的行/列存储单元)或者四次查找(对于数组类型的存储)。最有效的方法取决于你访问数据的方式和数据的结构。

如果你的例子确实是典型的,只有16个条目,你可以随便存储它,速度对于任何正常的负载来说都足够快。

3

我会把第一列的数据整理成一个有序的列表,然后使用标准库里的 bisect 模块来查找这些值——这样可以最快找到比目标值小的和大的索引。其他列的数据可以用一个和这个列表平行的列表来保存。

7

如果你想要一个计算效率最高的解决方案,并且不受标准库的限制,我推荐使用scipy和numpy。首先,把a到p的数组存成一个二维的numpy数组,然后把$4k-10k和1-4的数组存成一维的numpy数组。如果这两个一维数组都是单调递增的,可以用scipy的interpolate.interp1d;如果不是,而且你的示例数组和例子一样小,可以用interpolate.bsplrep(双变量样条表示法)。当然,你也可以自己写一个,不用管scipy。以下是一些例子:

# 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)

我上次检查(大约是2007年的一个版本的scipy)时,它只适用于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 不过这两个方法都需要比上面三个数组更复杂的数据结构。

撰写回答