2013-04-23 57 views
32

我能够使用python datetime对象读取和分割熊猫数据框,但是我只能在索引中使用现有日期。例如,这个工程:python熊猫数据帧按日期条件切片

>>> data 
<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 252 entries, 2010-12-31 00:00:00 to 2010-04-01 00:00:00 
Data columns: 
Adj Close 252 non-null values 
dtypes: float64(1) 

>>> st = datetime.datetime(2010, 12, 31, 0, 0) 
>>> en = datetime.datetime(2010, 12, 28, 0, 0) 

>>> data[st:en] 
      Adj Close 
Date     
2010-12-31  593.97 
2010-12-30  598.86 
2010-12-29  601.00 
2010-12-28  598.92 

但是,如果我使用的DF,我得到蟒蛇KeyError异常是不存在的开始或结束日期。

我的问题:如何查询数据框对象的日期范围;即使DataFrame中不存在开始日期和结束日期也是如此。熊猫是否允许基于范围的切片?

我使用熊猫版本0.10.1

回答

39

使用searchsorted先找到最近的次,然后用它来切。

In [15]: df = pd.DataFrame([1, 2, 3], index=[dt.datetime(2013, 1, 1), dt.datetime(2013, 1, 3), dt.datetime(2013, 1, 5)]) 

In [16]: df 
Out[16]: 
      0 
2013-01-01 1 
2013-01-03 2 
2013-01-05 3 

In [22]: start = df.index.searchsorted(dt.datetime(2013, 1, 2)) 

In [23]: end = df.index.searchsorted(dt.datetime(2013, 1, 4)) 

In [24]: df.ix[start:end] 
Out[24]: 
      0 
2013-01-03 2 
+0

如果我复制粘贴你的例子,它工作正常。但是我的程序中的开始和结束变量始终默认为数据帧的长度!我究竟做错了什么? - http://pastebin.com/raw.php?i=hfpHqF7s – 2013-04-23 22:21:18

+0

似乎你应该按照升序排列你的'DataFrame'。 – waitingkuo 2013-04-24 01:28:28

+0

谢谢,它在数据按升序排序时工作。 – 2013-04-24 06:21:46

23

简短的回答:您的数据排序(data.sort()),然后我想一切都会工作,你期待的方式。

是的,您可以使用不存在于DataFrame中的日期时间进行切片。例如:

In [12]: df 
Out[12]: 
        0 
2013-04-20 1.120024 
2013-04-21 -0.721101 
2013-04-22 0.379392 
2013-04-23 0.924535 
2013-04-24 0.531902 
2013-04-25 -0.957936 

In [13]: df['20130419':'20130422'] 
Out[13]: 
        0 
2013-04-20 1.120024 
2013-04-21 -0.721101 
2013-04-22 0.379392 

正如你所看到的,你甚至不必建立datetime对象;字符串工作。

因为索引中的日期时间不是顺序的,所以行为很奇怪。如果我们在这里洗牌我的例子指数...

In [17]: df 
Out[17]: 
        0 
2013-04-22 1.120024 
2013-04-20 -0.721101 
2013-04-24 0.379392 
2013-04-23 0.924535 
2013-04-21 0.531902 
2013-04-25 -0.957936 

...并采取相同的切片,我们得到了不同的结果。它返回范围内的第一个元素,并停止在范围外的第一个元素。

In [18]: df['20130419':'20130422'] 
Out[18]: 
        0 
2013-04-22 1.120024 
2013-04-20 -0.721101 
2013-04-24 0.379392 

这可能不是有用的行为。如果你想选择日期范围,首先按日期排序是否合理?

df.sort_index() 
+0

当我尝试这样做时,我得到一个python异常:TimeSeriesError:部分索引只对有序时间序列有效。 – 2013-04-23 22:27:11

+0

这个例外是自我解释 - 我错过了排序数据:(:(谢谢你,上面显示的基于文本的切片按预期工作)但是我使用了searchsorted函数,因为程序中的日期已经是datetime对象了。 – 2013-04-24 06:25:24

+2

df ['20130419':'20130422']是例外!即使与稀疏数据(例如指定索引中不存在的日期)。谢谢! – fantabolous 2014-06-26 04:10:45

4

您可以使用一个简单的面膜来实现:

date_mask = (data.index > start) & (data.index < end) 
dates = data.index[date_mask] 
data.ix[dates] 

顺便说一句,这个工程的分层索引为好。在这种情况下,data.index将替换为data.index.levels[0]或类似的。

+0

这个答案需要更多upvotes。我一直在寻找这个星期! – 2017-11-06 05:53:11