2016-12-01 11 views
8

Czy jest możliwe wyprodukowanie serii, która interpoluje jej wartość dla dowolnego indeksu. Mam predefiniowany schemat interpolacji, który chcę przepisać i wolałbym, aby osoba dzwoniąca sama nie zastosowała interpolacji, aby uniknąć jakichkolwiek możliwości błędu.Czy można skonstruować serię Pand, która automatycznie interpoluje?

class InterpolatedSeries(pd.Series): 
    pass # magic? 

s = pd.Series([1, 3], index=[1, 3]) 
i = InterpolatedSeries(s, forward='nearest', backward='nearest', middle='linear') 

Dzwoniący otrzyma i w wyniku i mogą teraz żądać żadnej wartości, a byłbym przekonany, wartość dostali, dostosowany przepisanej schematu interpolacji. Interpolacja z pewnością nie byłaby obliczalna (ponieważ nie wiemy, które punkty zażądają z wyprzedzeniem) lub buforowana (ponieważ nie wiemy, ile punktów będą wymagać), ale co ważne, nie ma żadnych komplikacji dla dzwoniącego.

Czy to możliwe?

>>> i[[0, 0.11234, 1, 2, 2.367, 3, 4]] 
... pd.Series([1, 1, 1, 2, 2.367, 3, 3], index=[0, 0.11234, 1, 2, 2.367, 3, 4]) 
+0

Czy możesz dokładniej określić, dlaczego chcesz, aby była to podklasa pd.Series? – DSM

+0

Intencją jest, aby funkcja biblioteczna zwracała coś, co do wszystkich celów zachowuje się z tym samym interfejsem, co pd.Series. Aby użytkownik mógł .to_csv, groupby itp., Gdyby chciał. – poulter7

+0

sprawdzić metody magii python. Prawdopodobnie możesz po prostu interpolować, gdy ustawisz wartość elementu. '__setitem__' jest wywoływane, gdy zmieniasz wartość pozycji' i [0] = 1', więc w metodzie '__setitem__' interpolujesz wartości przed ich ustawieniem lub ustaw wartość interpolując wszystkie wartości, następnie zresetuj wartości. Możesz także użyć '__getitem__' do interpolacji, gdy ktoś zapyta o wartość' variable = i [0] '. – HashSplat

Odpowiedz

5

Użyj __getitem__. To się nazywa metoda python Magic http://www.diveintopython3.net/special-method-names.html

class InterpolatedSeries(pd.Series): 
    def __init__(self, values, forward='nearest', backward='nearest', middle='linear'): 
     super().__init__(values) 
     self.forward = forward 
     self.backward = backward 
     self.middle = middle 

    def __getitem__(self, key): 
     # get the stored values 
     values = super().__getitem__(key) 
     # Do interpolation 
     return values 

lub

class InterpolatedSeries(pd.Series): 
    def __init__(self, values, forward='nearest', backward='nearest', middle='linear'): 
     super().__init__(values) 
     self.forward = forward 
     self.backward = backward 
     self.middle = middle 

    def __setitem__(self, key, value): 
     # Do interpolation 
     super().__setitem__(key, value) 

Inną alternatywą byłoby stworzenie jesteś właścicielem klasę, która współdziała z podstawowej struktury danych. Ta klasa nie dziedziczy po pd.Series, ale zamiast tego obiekt.

class InterpolatedSeries(object): 
    def __init__(self, values, forward='nearest', backward='nearest', middle='linear'): 
     self.data = values 
     self.forward = forward 
     self.backward = backward 
     self.middle = middle 

    def __getitem__(self, key): 
     values = self.data.__getitem__(key) 
     # Do interpolation 
     return values 

    def __getattribute__(self, key): # maybe __getattr__ if this doesn't work 
     """Return the stored pandas series item if the method or attribute was not found. This allows your to_csv method to work""" 
     try: 
      return super().__getattribute__(key) 
     except AttributeError: 
      pass 
     return self.data.__getattribute__(key) # Call the stored pandas series method if not found. 

    def __dir__(self): 
     """Return the list of attributes. (Most code autocomplete features use this, so this will find your pandas series methods for autocomplete in IDEs). """ 
     values = dir(self.data) 
     return values + super().__dir__() 

Powyższy prawdopodobnie nie jest najlepszym rozwiązaniem, ale to nie dodać pewną elastyczność poprzez ułatwienie dostępu do metod serii pandy w tle.

+0

Dzięki Nie wiem, dlaczego myślałem o bardziej skomplikowanych rzeczach niż __getitem__, to jest zgrabne, obsługuje nawet wywołania series.ix [n], ponieważ panda powraca do __getitem__, jeśli n nie jest dostępne w serii. Jednak myślę, że musisz zawinąć wynikowy __getitem__ w interpolowanej serii, określając oryginalną serię, w przeciwnym razie otrzymasz dziwne wyniki. – poulter7

+1

Prawidłowe. Będziesz musiał zawinąć wyniki interpolacji w innym obiekcie InterpolatedSeries. W ten sposób obiekt zachowuje oczekiwaną klasę. Proponuję uczynić go przyjaznym dla dziedziczenia, używając konstruktora 'self .__ class __()'. – HashSplat

Powiązane problemy