在带有熊猫时间段的特定时间戳之后选择第一个索引



这是一个分为两部分的问题,有一个直接的问题,一个更通用的问题。

我有一个熊猫时代,ts。在一定时间后了解第一个值。我可以做到这一点,

ts.ix[ts[datetime(2012,1,1,15,0,0):].first_valid_index()]

a)是否有更好,更笨拙的方法?

b)来自c,在处理这些不透明的,可能是可变的,但通常不是懒惰但并非总是类型时,我有一定的恐惧症。可以明确的是,当我做

ts[datetime(2012,1,1,15,0,0):].first_valid_index()

ts [dateTime(2012,1,1,1,15,0,0):]是pandas.timeseries对象吗?我可能会变异。

这是否意味着每当我进行切片时,都会在内存中分配TS的副本?这是否意味着这条无害的代码线实际上可以触发时间表的千兆字节的副本只是为了获得索引值?

,或者他们神奇地共享内存,如果一个对象被突变,则可以完成懒惰的副本?但是,您怎么知道哪种特定操作触发了副本?也许不切片,但是重命名列呢?在文档中似乎并不是这样。那会麻烦你吗?它应该打扰我,还是我应该学会不要担心并遇到探索者的问题?

一些设置:

In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: from datetime import datetime
In [4]: dates = [datetime(2011, 1, 2), datetime(2011, 1, 5), datetime(2011, 1, 7), datetime(2011, 1, 8), datetime(2011, 1, 10), datetime(2011, 1, 12)]
In [5]: ts = pd.Series(np.random.randn(6), index=dates)
In [6]: ts
Out[6]: 
2011-01-02   -0.412335
2011-01-05   -0.809092
2011-01-07   -0.442320
2011-01-08   -0.337281
2011-01-10    0.522765
2011-01-12    1.559876

好吧,现在回答您的第一个问题,a)是的,根据您的意图,笨拙的方式较少。这很简单:

In [9]: ts[datetime(2011, 1, 8):]
Out[9]: 
2011-01-08   -0.337281
2011-01-10    0.522765
2011-01-12    1.559876

这是A slice 包含所选日期之后的所有值。您可以按照:

选择第一个。
In [10]: ts[datetime(2011, 1, 8):][0]
Out[10]: -0.33728079849770815

在您的第二个问题上,(b) - 这种类型的索引是原始的切片,就像其他numpy阵列一样。它不是原件的副本。看到这个问题,或许多类似的问题:错误或功能:克隆带有切片的numpy数组

要演示,让我们修改切片:

In [21]: ts2 = ts[datetime(2011, 1, 8):]
In [23]: ts2[0] = 99

这更改了原始的次数对象TS,因为TS2是切片而不是副本。

In [24]: ts
Out[24]: 
2011-01-02    -0.412335
2011-01-05    -0.809092
2011-01-07    -0.442320
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876

如果您确实想要副本,则可以(通常)使用复制方法或(在这种情况下)使用截断:

In [25]: ts3 = ts.truncate(before='2011-01-08')
In [26]: ts3  
Out[26]: 
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876

更改此副本不会更改原件。

In [27]: ts3[1] = 99
In [28]: ts3
Out[28]: 
2011-01-08    99.000000
2011-01-10    99.000000
2011-01-12     1.559876
In [29]: ts                #The january 10th value will be unchanged. 
Out[29]: 
2011-01-02    -0.412335
2011-01-05    -0.809092
2011-01-07    -0.442320
2011-01-08    99.000000
2011-01-10     0.522765
2011-01-12     1.559876

此示例直接从WES的" Python进行数据分析"中。一探究竟。这很棒。

我不知道熊猫,一个一般答案:

您可以在Python中超载任何内容,他们必须在那里做到这一点。如果您在类上定义了一种特殊的方法__getitem__,则在使用obj[key]obj[start:stop]时称为(在前一种情况下仅用键作为参数,而后者则具有特殊的slice对象)。然后,您可以返回任何想要的东西。

这是显示__getitem__如何工作的示例:

class Foo(object):
    def __getitem__(self, k):
        if isinstance(k, slice):
            return k.start + k.stop # properties of the slice object
        else:
            return k

这给了您:

>>> f = range.Foo()
>>> f[42]
42
>>> f[23:42]
65

我假设在您的示例中,__getitem__方法返回一些特殊对象,其中包含DateTime对象以及对原始ts对象的引用。然后,当调用first_valid_index方法或类似方法时,该特殊对象可以使用该信息以稍后以后获取所需信息。(甚至不必像您的问题所建议的那样修改原始对象。)

tl; dr:学习不要担心: - )

加法:我很好奇,所以我实现了您上面描述的行为的最小示例:

class FilterableList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
        self.filter = FilterProxy(self)
class FilterProxy(object):
    def __init__(self, parent):
        self.parent = parent
    def __getitem__(self, sl):
        if isinstance(sl, slice):
            return Filter(self.parent, sl)
class Filter(object):
    def __init__(self, parent, sl):
        self.parent = parent
        self.sl = sl
    def eval(self):
        return [e for e in self.parent if self.sl.start <= e <= self.sl.stop]

>>> l = FilterableList([4,5,6,7])
>>> f = l.filter[6:10]
>>> f.eval()
[6, 7]
>>> l.append(8)
>>> f.eval()
[6, 7, 8]

最新更新