2015-04-07 8 views
2

Снова и снова в пандах я нахожу, что мне нужно разделить на определенное время. Например, за каждый день во временном ряду разделите каждое значение на значение в 12:00.Python pandas time series сравнить конкретные времена

Я чувствую, что это должно быть довольно простой операцией, но я не нашел простых решений.

Например, я хочу, чтобы выполнить функцию на каждый день во временных рядах:

x = df.groupby(df.index.date).apply(func) 

За каждый день, сделайте следующее:

def func(df): 
    st = df.between_time('10:00','10:00')['y-value'] 
    end = df.between_time('14:45','14:45')['y-value'] 
    return (st/end) 

Во-первых, есть ли способ сказать, df.at_time ('10: 00')? Кажется окольным писать здесь .between_time() здесь, но он работает. Я также пробовал df.index.time, но я не уверен, как сказать: == datetime.time (10,0), потому что это возвращает логический массив, а не просто значение в 10:00 утра.

Функция не работает, потому что, по моему мнению, это проблема индексации, она выплевывает N/A при каждом значении и выплевывает два значения за каждый день (то есть один в 10:00 и 14:45), Не один. Это работает, если они в одно и то же время, но не в разное время. Я убежден, что арифметические операции не работают чисто в разные даты.

Я также попытался:

def func(df): 
    st = df.reset_index().between_time('10:00','10:00')['mid'].values[0] 
    end = df.reset_index().between_time('14:45','14:45')['mid'].values[0] 
    return (st/end) 

И я получаю ошибку индексации говоря мне нужно вернуть DateTimeIndex. Я полагаю, что я не могу просто делить значения через, и он вернет это значение на соответствующую дату, но ему нужно вернуть какой-то объект (индекс, значение) pandas.

Любые идеи? Это обычная операция?

Вот что мой набор данных выглядит (используйте pd.read_clipboard() для чтения в):

     bid ask  mid 
2000-01-01 12:00:00 288.0 289.5 288.75 
2000-01-01 13:30:00 287.8 288.6 288.20000000000005 
2000-01-01 14:00:00 287.75 289.25 288.5 
2000-01-03 09:30:00 288.5 289.5 289.0 
2000-01-03 10:15:00 288.5 289.5 289.0 
2000-01-03 10:30:00 289.0 290.0 289.5 
2000-01-03 10:45:00 288.75 289.75 289.25 
2000-01-03 11:45:00 288.75 289.75 289.25 
2000-01-03 13:00:00 288.5 289.5 289.0 
2000-01-03 13:15:00 288.5 289.5 289.0 
2000-01-03 13:30:00 288.5 289.5 289.0 
2000-01-04 09:00:00 281.5 282.25 281.875 
2000-01-04 09:15:00 281.0 281.5 281.25 
2000-01-04 09:30:00 281.25 281.75 281.5 
2000-01-04 09:45:00 281.1 281.85 281.475 
2000-01-04 10:00:00 281.7 282.2 281.95 
2000-01-04 10:30:00 282.0 282.75 282.375 
2000-01-04 10:45:00 282.2 282.95 282.575 
2000-01-04 11:15:00 282.3 282.8 282.55 
2000-01-04 11:30:00 281.45 282.2 281.825 

UPDATE: Временное решение, но я искал что-то более чистого (возможно она не существует)

st_time, end_time = '8:00', '14:45' 
st, end = df.at_time(st_time), df.at_time(end_time) 
AM = st.merge(end, on='date', how='left').dropna() 
AM = AM.set_index(pd.DatetimeIndex(AM['date'])) 
AM['AM return'] = (AM[end_time]/AM[st_time]) - 1 
AM = AM.rename(columns={'price_x': st_time+' price', 'price_y': end_time+' price'}) 
+0

показать пример того, что вы ожидаете для вывода – Jeff

+0

У вас нет значения в течение 12 часов каждый день, только в первый день. –

+0

try return '(st/end.values)' – HYRY

ответ

0

Вот способ сделать то, что я думаю, что вы хотите.

Reindex оригинальная рамка, чтобы быть всеми датами в инклюзивном диапазоне. Это гарантирует, что «12: 00» будет существовать; forward-fill, чтобы использовать значения.

In [66]: y = df.reindex(pd.date_range(df.index.min().date(),(df.index.max() + pd.offsets.Day()).date(), closed='left', freq='15T'), method='ffill') 

In [67]: y.info() 
<class 'pandas.core.frame.DataFrame'> 
DatetimeIndex: 384 entries, 2000-01-01 00:00:00 to 2000-01-04 23:45:00 
Freq: 15T 
Data columns (total 3 columns): 
bid 336 non-null float64 
ask 336 non-null float64 
mid 336 non-null float64 
dtypes: float64(3) 
memory usage: 12.0 KB 

разделите новую серию на значения «12: 00». Обратите внимание, что вам нужно отбросить индекс (с .values) для его правильной передачи. Reindex вернитесь к исходному фрейму.

In [68]: (y/y.groupby(y.index.date).transform(lambda x: x.at_time('12:00').values)).reindex(df.index) 
Out[68]: 
          bid  ask  mid 
2000-01-01 12:00:00 1.000000 1.000000 1.000000 
2000-01-01 13:30:00 0.999306 0.996891 0.998095 
2000-01-01 14:00:00 0.999132 0.999136 0.999134 
2000-01-03 09:30:00 0.999134 0.999137 0.999136 
2000-01-03 10:15:00 0.999134 0.999137 0.999136 
2000-01-03 10:30:00 1.000866 1.000863 1.000864 
2000-01-03 10:45:00 1.000000 1.000000 1.000000 
2000-01-03 11:45:00 1.000000 1.000000 1.000000 
2000-01-03 13:00:00 0.999134 0.999137 0.999136 
2000-01-03 13:15:00 0.999134 0.999137 0.999136 
2000-01-03 13:30:00 0.999134 0.999137 0.999136 
2000-01-04 09:00:00 1.000178 1.000177 1.000177 
2000-01-04 09:15:00 0.998401 0.997519 0.997960 
2000-01-04 09:30:00 0.999289 0.998405 0.998847 
2000-01-04 09:45:00 0.998756 0.998760 0.998758 
2000-01-04 10:00:00 1.000888 1.000000 1.000444 
2000-01-04 10:30:00 1.001954 1.001949 1.001952 
2000-01-04 10:45:00 1.002665 1.002658 1.002661 
2000-01-04 11:15:00 1.003020 1.002126 1.002573 
2000-01-04 11:30:00 1.000000 1.000000 1.000000 

Это должно быть надежным для вашего диапазона ввода и векторизации. Я думаю, что синтаксис/простота использования может быть улучшена.

+0

. Я проверю это –