繁体   English   中英

使用日期作为索引创建列表

[英]Creating a list using a date as index

我创建了一个使用日期列表作为索引的列表,如下所示:

>>> import datedlist
>>> import datetime
>>> dates = [datetime.date(2012,1,x) for x in range(2,6)]
>>> values = range(4,8)
>>> dates
[datetime.date(2012, 1, 2), datetime.date(2012, 1, 3), datetime.date(2012, 1, 4), datetime.date(2012, 1, 5)]
>>> dl = datedlist.DatedList(values, dates)
>>> dl
[4, 5, 6, 7]
>>> dl[datetime.date(2012,1,3)]
5

到目前为止,一切都很好,但我也希望能够用切片(不延长切片),像这样(以下不能正常工作-这是我想要的结果):

>>> datedlist[datetime.date(2012,1,3):datetime.date(2012,1,4)]
[5, 6]

这是我对此的尝试(显然不起作用):

class DatedList(list):

    def __init__(self, values, dates):
        self.dates = dates
        list.__init__(self, values)

    def __getitem__(self, date):
        if isinstance(date, slice):
            start = self.dates.index(slice[0])
            end = self.dates.index(slice[1])
            return [list.__getitem__(self, index) for index in range(start, end)]
        elif isinstance( date, datetime.date ) :
            index = self.dates.index(date)
            return list.__getitem__(self, index)
        elif isinstance(date, int):
            if date < 0:
                date += len(self)
            if date >= len(self):
                raise IndexError, "index out of range {}".format(date)
            return list.__getitem__(self, date)
        else:
            raise TypeError, "Invalid argument type."

切片[0]和切片[1]仅用于解释我的意图。 isinstance(date,int)仅用于调试 - 将删除生产代码。

这是一个问题 :如何实现使用datetime.date对象作为索引的切片?

编辑(在gnibblers第2条评论之后):我也尝试过getslice(即使文档说getslice已经过时)。 然后该类看起来像这样(由于语法,isinstance-slice位被注释掉):

class DatedList(list):

    def __init__(self, values, dates):
        self.dates = dates
        list.__init__(self, values)

    def __contains__(self, date):
        return date in self.dates

    def __getslice__(self, fromdate, todate):
        i_from = self.get_index(fromdate)
        i_to = self.get_index(todate)
        print i_from, i_to
        return [list.__getitem__(self, i) for i in range(i_from, i_to)]

    def __getitem__(self, date):
        if isinstance(date, slice):
            pass
#            start = self.dates.index(slice[0])
#            end = self.dates.index(slice[1])
#            return [list.__getitem__(self, i) for i in range(start, end)]
        elif isinstance(date, datetime.date):
            index = self.get_index(date)
            return list.__getitem__(self, index)
        elif isinstance(date, int):
            if date < 0:
                date += len(self)
            if date >= len(self):
                raise IndexError, "index out of range {}".format(date)
            return list.__getitem__(self, date)
        else:
            raise TypeError, "Invalid argument type."

    def get_index(self, date):
        if date in self.dates:
            index = self.dates.index(date)
        elif date < self.dates[0]:
            index = 0
        elif date > self.dates[-1]:
            index = len(self.dates) - 1
        return index

结果是:

>>> print dl[datetime.date(2012,1,3):datetime.date(2012,1,5)]
>>> None

显然,完全没有使用过,因为打印没有被执行。 看来getitem在请求切片时执行,但我似乎无法在切片中使用datetime.date。 /编辑

注意:显然,将子类列入子列并不是一个好主意,但到目前为止,我尝试过的替代方案似乎都没有更好(或根本没有):

  • 从头开始构建一个类:我无法使[]表示法工作:

     dl = DatedList(values, dates) value = dl[some_date] # I want this to work value = dl.value(same_date) # I don't want this 
  • 我考虑使用dict,但我的列表需要订购,我也需要使用切片。

  • 我也尝试将collections.Sequence子类化,但结果是:

    TypeError:描述符' init '需要'list'对象但收到'DatedList'

您可能希望查看一些现有的时间序列实现,而不是重新实现它。 熊猫scikits.timeseries一样非常好。

作为一个例子,与熊猫:

In [1]: from pandas import Series, DateRange

In [2]: import datetime

In [3]: ts = Series(range(12), index=DateRange('1/1/2000', periods=12, freq='T'))

In [4]: ts
Out[4]: 
2000-01-03     0
2000-01-04     1
2000-01-05     2
2000-01-06     3
2000-01-07     4
2000-01-10     5
2000-01-11     6
2000-01-12     7
2000-01-13     8
2000-01-14     9
2000-01-17    10
2000-01-18    11

In [5]: ts[datetime.datetime(2000,1,10):]
Out[5]: 
2000-01-10     5
2000-01-11     6
2000-01-12     7
2000-01-13     8
2000-01-14     9
2000-01-17    10
2000-01-18    11

或者,您可以调查那里的源代码并重新实现您的具体情况。

这是一个非常简单的示例,基本上您将参数传递给__getitem__并将它们传递给映射,以便您可以利用构建列表行为。

至于你提到的__getslice__是过时的, __getitem__只需要注意到它已经通过了slice ,并用它妥善处理。

import datetime
class DatedList(list):

    def __init__(self, values, dates):
        list.__init__(self, values)
        self.dates = dates
        self._dt_to_idx = {k:v for v,k in enumerate(dates)}

    def __getitem__(self, arg):
        if isinstance(arg, slice):
            start = self._dt_to_idx[arg.start]
            stop = self._dt_to_idx[arg.stop]
            return list.__getitem__(self, slice(start, stop, arg.step))
        else:
            return list.__getitem__(self, self._dt_to_idx[arg])    


dates = [datetime.date(2012,1,x) for x in range(2,6)]
dl = DatedList([1,2,3,4], dates)
print dl[dates[2]]
print dl[dates[1]:dates[3]]

如果你需要一个更复杂的映射 - 处理跳过的日期等,只需定义一个方法来进行映射并调用你使用self._dt_to_idx[...]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM