Python pandas时间序列比较具体时间

时间:2015-04-07 22:14:53

标签: python datetime pandas time-series normalization

大熊猫一遍又一遍,我发现我必须在特定的时间内分开。例如,对于时间序列中的每一天,将每个值除以中午12:00的值。

我觉得这应该是一个相当简单的操作,但我找不到简单的解决方案。

例如,我想在时间序列中每天执行一项功能:

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的值。 / p>

该功能不起作用,因为我认为是一个索引问题,它会在每个值上吐出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

更新:暂时修复,但我正在寻找更清洁的东西(它可能不存在)

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'})

1 个答案:

答案 0 :(得分:0)

这是一种做我想要的想法的方法。

将原始帧重新索引为包含范围内的所有日期。这确保'12:00'存在;向前填充以传播价值观。

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)以正确地广播它。重新索引回原始框架。

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

这应该对您的输入范围和矢量化都很稳健。但是我认为可以改进语法/易用性。