是否可能构建一个可以自动插值的Pandas Series?

8

是否可能生成一个可以插值任何给定索引的系列?我有一个预定义的插值方案,希望我自己指定,而不是让调用者自己应用插值,以避免任何可能的错误。

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

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

调用者将会收到i作为结果,他们现在可以请求任何值,并且我有信心他们获得的值符合规定的插值方案。这种插值肯定不是预先计算的(因为我们不知道他们会提前请求哪些点),也不能被缓存(因为我们不知道他们会请求多少个点),但重要的是对于调用者来说没有任何复杂性。
这是否可能?
>>> 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])

你能更具体地说明为什么你希望这个类是 pd.Series 的子类吗? - DSM
这个库函数的目的是返回一个行为与 pd.Series 相同接口的对象,以便用户可以进行 .to_csv、groupby 等操作。 - poulter7
查找Python魔术方法。当您设置项目值时,您可能只需插入值。更改项的值i[0]=1时调用__setitem__方法,因此在__setitem__方法中,在设置值之前插入值,或者在设置值之后插入所有值再重置值。当有人请求值variable=i[0]时,也可以使用'getitem'进行插值。 - justengel
1个回答

5

使用__getitem__方法。它被称为Python的魔术方法,详见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

或者
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)

另一个选择是创建自己的类,与底层数据结构进行交互。这个类不会继承pd.Series,而是继承一个对象。

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__()

以上可能不是最佳方法,但它增加了一些灵活性,通过使访问pandas系列方法更加容易来实现。


谢谢。我不知道为什么我一直在想比 getitem 更复杂的事情,这很好,它甚至处理 series.ix[n] 调用,因为 pandas 如果在系列中找不到 n,则会回退到 __getitem__。然而,我认为您需要将结果的 getitem 包装在一个插值系列中,指定原始系列,否则您将得到奇怪的结果。 - poulter7
1
正确。您需要将插值结果包装在另一个InterpolatedSeries对象中。这样,对象就保留了预期的类。我建议您使用构造函数self.__class__()使其友好继承。 - justengel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接