2014-12-21 10 views
7

Attualmente sto scrivendo una definizione pitone chiamato f_from_data che utilizza punto di appoggio trovare su una linea finora ho scritto questo:Come per la produzione di una "funzione Callable"

def f_from_data(xs, ys, x): 
    xfine = np.linspace(min(xs), max(xs), 10000) 
    y0 = inter.interp1d(xs, ys, kind = 'linear') 
    ans = (y0(xfine))[numpy.searchsorted(xfine, x)] 
    ans = round(ans,2) 
    return ans 

Questo mi sta dando quello che voglio Devo fare in modo che possa inserire:

f = f_from_data([3, 4, 6], [0, 1, 2]) 
print f(3) 
>>>0.0 

Come faccio a fare questo? Mi sono guardato intorno ma non riesco a trovare nulla, perché penso che sia davvero banale, ma mi manca solo qualcosa.

+0

FYI, questo processo è chiamato [applicazione funzione parziale] (http://en.m.wikipedia.org/wiki/Partial_application). – Kevin

risposta

12

Uso functools.partial:

from functools import partial 

f = partial(f_from_data, [3, 4, 6], [0, 1, 2]) 

partial creerà un oggetto richiamabile con i primi 2 argomenti già.

2

Forse qualcosa del genere?

def f_from_data(xs, ys): 
    def interpolate(x): 
     xfine = np.linspace(min(xs), max(xs), 10000) 
     y0 = inter.interp1d(xs, ys, kind = 'linear') 
     ans = (y0(xfine))[numpy.searchsorted(xfine, x)] 
     ans = round(ans,2) 
     return ans 
    return interpolate 

Avviso - Non conosco bene matplotlib per dire se il codice è corretto.

3

interpolate.interp1d restituisce un callable:

import scipy.interpolate as interpolate 

f_from_data = interpolate.interp1d 
f = f_from_data([3, 4, 6], [0, 1, 2]) 
print(f(3)) 

cede

0.0 

Dal f_from_data può essere assegnato a interpolate.interp1d, potrebbe non essere necessario f_from_data a tutti. Ora, è vero che questo non taglia la gamma x in 10000 punti griglia, e usa searchsorted per scattare il valore x su un punto griglia vicino, ma in generale non vorrai farlo comunque poiché interp1d ti dà un interpolazione lineare migliore senza di essa.

1

L'approccio più generale sarebbe quello di creare una classe con un metodo __call__, quindi qualcosa di simile:

class f_from_data(object): 
    def __init__(self, xs, ys): 
     self.xfine = np.linspace(min(xs), max(xs), 10000) 
     self.y0 = inter.interp1d(xs, ys, kind = 'linear') 
    def __call__(self, x): 
     ans = (self.y0(self.xfine))[numpy.searchsorted(self.xfine, x)] 
     return round(ans, 2) 
+0

Anche se questo potrebbe essere comune in altri contesti, sarebbe * estremamente * insolito in codice numpy. – sapi

+0

Cosa lo rende insolito nel codice di Numpy? È il modo, ad es. 'scipy.interpolate' fa funzionare tutti gli interpolatori 1D con funzione di ritorno, vedi [qui] (https://github.com/scipy/scipy/blob/v0.14.0/scipy/interpolate/polyint.py#L21), come 'numpy.poly1d' gestisce le funzioni di valutazione polinomiale, vedi [qui] (https://github.com/numpy/numpy/blob/3ef77eea0d9c2cd76bc9b89b04a32f1322f842d5/numpy/lib/polynomial.py#L939), o' numpy.vectorize' rende funzioni vettoriali, vedere [qui] (https://github.com/numpy/numpy/blob/3ef77eea0d9c2cd76bc9b89b04a32f1322f842d5/numpy/lib/function_base.py#L1577). – Jaime

2

Se quello che vuoi è semplice, qui si tratta di una soluzione semplice

>>> f = lambda x: f_from_data([3, 4, 6], [0, 1, 2], x) 
>>> print f(3) 
0.0 
>>> 

Se non ti piace lambda

>>> def f(x): return f_from_data([3, 4, 6], [0, 1, 2], x) 

In entrambi i casi m assicurarsi che f_from_data sia incluso nell'ambito della definizione della funzione ausiliaria.

Problemi correlati