2009-05-24 66 views
6

我有20多個類似於表1的表。其中所有字母都代表實際值。數據存儲以簡化Python中的數據插值

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中(文件,字典,元組,或列表的字典的元組)的數據,這樣我就可以最有效地和正確地執行雙線性插值?

回答

7

如果你想要我能想到的最具計算效率的解決方案,並且不侷限於標準庫,那麼我會推薦scipy/numpy。首先,將a..p數組存儲爲2D numpy數組,然後將$ 4k-10k和1-4數組存儲爲1D 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的的)只工作了這樣的4×4陣列單調遞增x和y)

的數組爲小陣列,我想你想用這個: 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 但它們都需要與上例中的三個數組不同的更詳細的數據結構。

+0

請舉一些例子,我有類似的問題,但不能破解它在O(日誌n) – 2009-05-24 10:39:07

0

雙線性插值沒有什麼特別的地方讓你的用例特別奇怪;您只需執行兩次查找(對於全行/列的存儲單元)或四次查找(對於陣列類型存儲)。最有效的方法取決於您的訪問模式和數據結構。

如果您的示例具有真正的代表性,並且有16個條目,您可以根據需要存儲它,並且對於任何類型的理智加載都足夠快。

3

我會保留第一列的排序列表,並使用標準庫中的bisect模塊來查找值 - 這是獲取立即更低和立即更高索引的最佳方法。其他列可以保存爲另一個列表與此列表平行。