55

我可以使用 python datetime 对象读取和切片 pandas 数据帧,但是我被迫只使用索引中的现有日期。例如,这有效:

>>> 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 中不存在的开始或结束日期,我会得到 python KeyError。

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

我正在使用熊猫版本 0.10.1

4

5 回答 5

55

使用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.iloc[start:end]
Out[24]: 
            0
2013-01-03  2
于 2013-04-23T18:22:19.250 回答
34

简短回答:对您的数据进行排序 ( 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

如您所见,您甚至不必构建日期时间对象;字符串工作。

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

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()
于 2013-04-23T21:07:12.130 回答
19

您可以使用一个简单的掩码来完成此操作:

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

顺便说一句,这也适用于分层索引。在那种情况下,data.index将被替换为data.index.levels[0]或类似的。

于 2017-05-02T02:12:40.827 回答
1

我对其他方法有困难,但我发现以下方法对我有用:

# Set the Index to be the Date
df['Date'] = pd.to_datetime(df['Date_1'], format='%d/%m/%Y')
df.set_index('Date', inplace=True)

# Sort the Data
df = df.sort_values('Date_1')

# Slice the Data
From = '2017-05-07'
To   = '2017-06-07'
df_Z = df.loc[From:To,:]
于 2018-05-18T15:59:41.210 回答
1
target_date = pd.Timestamp('2020-05-10')

df[df['DATE'].dt.date == (dt.date(target_date.year, target_date.month, target_date.day))]

此行将让您选择所有符合条件的日期,以防您不需要将“日期列”设置为索引。

于 2021-09-06T17:37:17.633 回答