Подтвердить что ты не робот

Python pandas резка данных по датам

Я могу читать и нарезать pandas dataframe с использованием объектов 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, я получаю python KeyError.

Мой вопрос: как я запрашиваю объект dataframe для диапазона дат; даже когда даты начала и окончания отсутствуют в DataFrame. Разрешает ли pandas разрез на основе диапазона?

Я использую pandas версию 0.10.1

4b9b3361

Ответ 1

Используйте searchsorted чтобы 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

Ответ 2

Короткий ответ: Сортируйте свои данные (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()

Ответ 3

Для достижения этой цели вы можете использовать простую маску:

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

Кстати, это работает и для иерархической индексации. В этом случае data.index будет заменен на data.index.levels[0] или аналогичным.

Ответ 4

У меня были трудности с другими подходами, но я обнаружил, что следующий подход работал для меня:

# 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,:]