Панды Python, как усечь DatetimeIndex и заполнить недостающие данные только через определенный интервал

 2012-10-08 07:12:22            0.0    0          0  2315.6    0     0.0    0
 2012-10-08 09:14:00         2306.4   20  326586240  2306.4  472  2306.8    4
 2012-10-08 09:15:00         2306.8   34  249805440  2306.8  361  2308.0   26
 2012-10-08 09:15:01         2308.0    1   53309040  2307.4   77  2308.6    9
 2012-10-08 09:15:01.500000  2308.2    1  124630140  2307.0  180  2308.4    1
 2012-10-08 09:15:02         2307.0    5   85846260  2308.2  124  2308.0    9
 2012-10-08 09:15:02.500000  2307.0    3  128073540  2307.0  185  2307.6   11
 ......
 2012-10-09 07:19:30            0.0    0          0  2276.6    0     0.0    0
 2012-10-09 09:14:00         2283.2   80   98634240  2283.2  144  2283.4    1
 2012-10-09 09:15:00         2285.2   18  126814260  2285.2  185  2285.6    3
 2012-10-09 09:15:01         2285.8    6   98719560  2286.8  144  2287.0   25
 2012-10-09 09:15:01.500000  2287.0   36  144759420  2288.8  211  2289.0    4
 2012-10-09 09:15:02         2287.4    6  109829280  2287.4  160  2288.6    5
 ......

У меня есть DataFrame, содержащий несколько дней биржевых торговых данных, как указано выше. Данные, которые я хочу получить, взяты из 9:00:00AM - 11:30:00AM и 13:00:00 - 15:15:00, поэтому я хотел бы сделать две вещи:

  1. для каждой даты в DataFrame усекать только данные в диапазоне 9:00:00AM - 11:30:00AM и 13:00:00 - 15:15:00
  2. с диапазоном в 1., заполнить недостающие данные с частотой 500 milliseconds

функции усечения pandas позволяют мне усекать только в соответствии с датой, но я хотел бы урезать в соответствии с datetime.time здесь. Также как заполнить недостающие данные только для интересующего меня интервала.

Большое спасибо.


person tesla1060    schedule 03.02.2013    source источник


Ответы (1)


  1. для каждой даты в DataFrame усекать только данные в диапазоне 9:00:00 - 11:30:00 и 13:00:00 - 15:15:00

Для этого используйте индекс slicing, например:

df = df[start_timestamp:end_timestamp]
  1. с диапазоном в 1., заполнить недостающие данные с частотой 500 миллисекунд

Создайте новый кадр данных с индексом 500 мс. Объедините этот фрейм данных с исходным, используя внешний присоединиться. Это дает вам кадр данных со строками через равные промежутки времени. Строки для отсутствующих наблюдений будут содержать значения NaN. Затем заполните недостающие значения NaN с помощью fillna.

Пример:

In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: data = pd.DataFrame({"value": np.arange(5)}, index=pd.date_range("2013/02/03", periods=5, freq="3Min"))

In [4]: data
Out[4]: 
                     value
2013-02-03 00:00:00      0
2013-02-03 00:03:00      1
2013-02-03 00:06:00      2
2013-02-03 00:09:00      3
2013-02-03 00:12:00      4

In [5]: filler = pd.DataFrame({"value": [100] * 15}, index=pd.date_range("2013/02/03", periods=15, freq="1Min"))                                                                           

In [6]: filler
Out[6]: 
                     value
2013-02-03 00:00:00    100
2013-02-03 00:01:00    100
2013-02-03 00:02:00    100
2013-02-03 00:03:00    100
2013-02-03 00:04:00    100
2013-02-03 00:05:00    100
2013-02-03 00:06:00    100
2013-02-03 00:07:00    100
2013-02-03 00:08:00    100
2013-02-03 00:09:00    100
2013-02-03 00:10:00    100
2013-02-03 00:11:00    100
2013-02-03 00:12:00    100
2013-02-03 00:13:00    100
2013-02-03 00:14:00    100

In [7]: merged = filler.merge(data, how='left', left_index=True, right_index=True)                                                                                                         

In [8]: merged["value"] = np.where(np.isfinite(merged.value_y), merged.value_y, merged.value_x)                                                                                            

In [9]: merged
Out[9]: 
                     value_x  value_y  value
2013-02-03 00:00:00      100        0      0
2013-02-03 00:01:00      100      NaN    100
2013-02-03 00:02:00      100      NaN    100
2013-02-03 00:03:00      100        1      1
2013-02-03 00:04:00      100      NaN    100
2013-02-03 00:05:00      100      NaN    100
2013-02-03 00:06:00      100        2      2
2013-02-03 00:07:00      100      NaN    100
2013-02-03 00:08:00      100      NaN    100
2013-02-03 00:09:00      100        3      3
2013-02-03 00:10:00      100      NaN    100
2013-02-03 00:11:00      100      NaN    100
2013-02-03 00:12:00      100        4      4
2013-02-03 00:13:00      100      NaN    100
2013-02-03 00:14:00      100      NaN    100

In [10]: merged['2013-02-03 00:01:00':'2013-02-03 00:10:00']                                                                                                                                
Out[10]: 
                     value_x  value_y  value
2013-02-03 00:01:00      100      NaN    100
2013-02-03 00:02:00      100      NaN    100
2013-02-03 00:03:00      100        1      1
2013-02-03 00:04:00      100      NaN    100
2013-02-03 00:05:00      100      NaN    100
2013-02-03 00:06:00      100        2      2
2013-02-03 00:07:00      100      NaN    100
2013-02-03 00:08:00      100      NaN    100
2013-02-03 00:09:00      100        3      3
2013-02-03 00:10:00      100      NaN    100
person Maxim Egorushkin    schedule 03.02.2013
comment
спасибо, как видите, мой индекс имеет форму полной метки времени, например 2012-10-08 07:12:22, а ваш [start_timestamp:end_timestamp] имеет вид datetime.time? если это так, кажется, не работает. он выдает недопустимое исключение нарезки. - person tesla1060; 03.02.2013
comment
@tesla1060 добавил полный пример - person Maxim Egorushkin; 03.02.2013
comment
спасибо за пример, который решил мой второй вопрос. Но первый, то, как вы это делаете, это merged['2013-02-03 00:01:00':'2013-02-03 00:10:00'], вы предполагаете, что знаете дату как 2013-02-03, моя проблема в том, что у меня есть несколько дат, и на каждую дату я хотел бы данные от 00:01:00 до 00:10:00, есть ли более простой способ добиться этого, кроме указания полной метки времени['2013-02-03 00:01:00':'2013-02-03 00:10:00'] , но, возможно, просто использовать часть datetime.time ['00:01:00':'00:10:00'] - person tesla1060; 03.02.2013
comment
@ tesla1060 tesla1060 Вероятно, вы можете создать двухуровневый индекс ['date','time'], а затем применить временную фильтрацию для второго уровня, но сейчас это выходит за рамки моего текущего уровня панд-фу. - person Maxim Egorushkin; 03.02.2013