可以pandas.DatetimeIndex记住是否关闭?

eum*_*iro 5 python datetime pandas

我有一个pandas.DatetimeIndex间隔['2018-01-01', '2018-01-04')(开始包括,结束排除)和freq=1D:

>>> index = pd.DatetimeIndex(start='2018-01-01',
                             end='2018-01-04',
                             freq='1D',
                             closed='left')
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03'],
              dtype='datetime64[ns]',
              freq='D')
Run Code Online (Sandbox Code Playgroud)

如何end='2018-01-04'再次获取正确的打开属性?我需要它用于具有时间戳范围的数据库查询.

  1. 没有 index.end
  2. index[-1] 回报 '2018-01-03'
  3. index[-1] + index.freq 在这种情况下工作但是错了 freq='2D'

iva*_*eev 5

没有办法,因为在构造对象后这些信息会丢失.在创建时,间隔将展开到生成的序列中:

pandas/core/indexes/datetimes.py:

class DatetimeIndex(<...>):

    <...>

    @classmethod
    def _generate(cls, start, end, periods, name, freq,
                  tz=None, normalize=False, ambiguous='raise', closed=None):
        <...>

                index = tools.to_datetime(np.linspace(start.value,
                                                      end.value, periods),
                                          utc=True)
                <...>

        if not left_closed and len(index) and index[0] == start:
            index = index[1:]
        if not right_closed and len(index) and index[-1] == end:
            index = index[:-1]
        index = cls._simple_new(index, name=name, freq=freq, tz=tz)
        return index
Run Code Online (Sandbox Code Playgroud)

closed信息也没有保存在任何地方,所以你甚至无法从第一个/最后一个点和步骤推断它.


您可以子类化DatetimeIndex并保存此信息.请注意,它是一个不可变类型,因此您需要覆盖__new__而不是__init__:

import inspect, collections
class SiDatetimeIndex(pd.DatetimeIndex):

    _Interval = collections.namedtuple('Interval',
            ('start','end','freq','closed'))
    #add 'interval' to dir(): DatetimeIndex inherits pandas.core.accessor.DirNamesMixin
    _accessors = pd.DatetimeIndex._accessors | frozenset(('interval',))

    def __new__(cls, *args, **kwargs):
        base_new = super(SiDatetimeIndex,cls).__new__
        callargs = inspect.getcallargs(base_new,cls,*args,**kwargs)
        result = base_new(**callargs)
        result.interval = cls._Interval._make(callargs[a] for a in cls._Interval._fields)
        return result


In [31]: index = SiDatetimeIndex(start='2018-01-01',
...:                              end='2018-01-04',
...:                              freq='1D',
...:                              closed='left')

In [38]: index.interval
Out[38]: Interval(start='2018-01-01', end='2018-01-04', freq='1D', closed='left')
Run Code Online (Sandbox Code Playgroud)

不要指望虽然所有pandas方法(包括你的类中继承的方法)现在都会神奇地开始创建被覆盖的类.为此,您需要在pandas这些方法使用的已加载模块中替换对基类的实时引用.或者,您可以只更换原件__new__- 然后无需替换参考.