2014-12-21 11 views
7

Obecnie piszę definicję Pythona o nazwie f_from_data który wykorzystuje punkt interpolacji find na linii tej pory pisałem tak:Jak stworzyć „funkcję płatnych na żądanie”

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 

To daje mi to, czego chcą Muszę to zrobić, abym mógł wprowadzić:

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

Jak mam to zrobić? Rozglądałem się dookoła, ale nie mogę niczego znaleźć, bo myślę, że to naprawdę banalne, ale po prostu brakuje mi czegoś.

+0

FYI, proces ten nazywa się [aplikacja funkcji cząstkowej] (http://en.m.wikipedia.org/wiki/Partial_application). – Kevin

Odpowiedz

12

Korzystanie functools.partial:

from functools import partial 

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

partial stworzy wpłacone obiekt z pierwszych 2 argumentów już przedstawionych.

2

Być może coś takiego?

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 

Ostrzeżenie - Nie wiem, Matplotlib wystarczająco dobrze, aby powiedzieć, czy kod jest poprawny.

3

interpolate.interp1d zwraca wywoływalnym:

import scipy.interpolate as interpolate 

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

daje

0.0 

Od f_from_data mogą być przypisane do interpolate.interp1d, może nie trzeba f_from_data w ogóle. Prawdą jest, że to nie przerywa zakresu x do 10000 punktów siatki i używa wyszukiwania w celu przyciągnięcia wartości x do pobliskiego punktu siatki, ale generalnie nie chciałbyś tego robić, ponieważ interp1d daje ci lepsza interpolacja liniowa bez niego.

1

Im bardziej ogólne podejście byłoby utworzyć klasę z metodą __call__, więc coś takiego:

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

Chociaż może to być powszechne w innych kontekstach, byłoby to * wyjątkowo * niezwykłe w przypadku kodu numpy. – sapi

+0

Co sprawia, że ​​jest to niezwykłe w przypadku numpy kodu? To jest droga, np. 'scipy.interpolate' sprawia, że ​​wszystkie jego interpretery 1D zwracają funkcjonalność, zobacz [tutaj] (https://github.com/scipy/scipy/blob/v0.14.0/scipy/interpolate/polyint.py#L21), jak 'numpy.poly1d' obsługuje funkcje oceniające wielomian, zobacz [tutaj] (https://github.com/numpy/numpy/blob/3ef77eea0d9c2cd76bc9b89b04a32f1322f842d5/numpy/lib/polynomial.py#L939) lub' numpy.vectorize' robi funkcje wektorowe, patrz [tutaj] (https://github.com/numpy/numpy/blob/3ef77eea0d9c2cd76bc9b89b04a32f1322f842d5/numpy/lib/function_base.py#L1577). – Jaime

2

Jeśli to, co chcesz, jest prosta, tutaj jest to proste rozwiązanie

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

Jeśli lubisz lambda

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

W obu przypadkach m Upewnij się, że f_from_data jest w zasięgu podczas definiowania funkcji pomocniczej.

Powiązane problemy