2009-05-24 15 views
6

Ho 20+ tabelle simili alla tabella 1. Dove tutte le lettere rappresentano valori reali.Archiviazione dati per facilitare l'interpolazione dei dati in 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 

Un input utente può essere ad esempio, (2.4, 24594) che è un valore compreso tra f, g, j e k. La mia definizione di funzione Python e lo pseudo-codice per calcolare questa interpolazione bilineare è la seguente.

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 

Come devo conservare i dati dalla tabella 1 (un file, un dict, tuple di tuple, o dict di liste), in modo da poter eseguire l'interpolazione bilineare più efficace e corretto?

risposta

7

Se si desidera la soluzione più efficiente dal punto di vista computazionale che si possa pensare e che non sia limitata alla libreria standard, quindi raccomanderei scipy/numpy. Per prima cosa, memorizza l'array a..p come array di numpy 2D e quindi entrambi gli array $ 4k-10k e 1-4 come array numpy 1D. Usa scipy's interpolate.interp1d se entrambi gli array 1D sono monotonicamente in aumento, o interpolate.bsplrep (rappresentazione spline bivariata) se no e gli array di esempio sono piccoli come il tuo esempio. O semplicemente scrivi il tuo e non preoccuparti di Scipy. Ecco alcuni esempi:

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

L'ultima volta che ho controllato (una versione di SciPy dal 2007-ish) funzionava solo per monotona crescente array di x ed y)

per piccoli array simili 4x4 matrice , Penso che tu voglia usare questo: http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.bisplrep.html#scipy.interpolate.bisplrep che gestirà superfici di forma più interessante e la funzione deve essere creata solo una volta. Per gli array più grandi, penso che tu voglia questo (non sono sicuro se questo ha le stesse restrizioni dell'interp1d): http://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp2d.html#scipy.interpolate.interp2d ma entrambi richiedono una struttura di dati diversa e più dettagliata dei tre array nell'esempio sopra.

+0

Si prega di dare alcuni esempi, ho un problema simile, ma non posso rompere in O (log n) –

+0

Mi piace perché sto già usando Numpy nella mia applicazione: D grazie – dassouki

0

Non c'è niente di speciale nell'interpolazione bilineare che rende particolarmente strano il tuo caso d'uso; devi solo fare due ricerche (per unità di memoria di righe/colonne complete) o quattro ricerche (per l'archiviazione di tipo array). Il metodo più efficiente dipende dai tuoi schemi di accesso e dalla struttura dei dati.

Se il tuo esempio è veramente rappresentativo, con 16 voci totali, puoi memorizzarlo come vuoi e sarà abbastanza veloce per qualsiasi tipo di carico sano.

3

Conserverei un elenco ordinato della prima colonna e utilizzerò il modulo bisect nella libreria standard per cercare i valori: è il modo migliore per ottenere gli indici immediatamente inferiori e immediatamente più alti. Ogni altra colonna può essere mantenuta come un altro elenco parallelo a questo.

Problemi correlati