【问题标题】:Python pandas time series compare specific timesPython pandas时间序列比较具体时间
【发布时间】:2015-06-12 16:24:41
【问题描述】:

在pandas中一遍又一遍,我发现我必须通过一个特定的时间来划分。例如,对于时间序列中的每一天,将每个值除以下午 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 的值。

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

【问题讨论】:

  • 显示一个您期望输出的示例
  • 你没有每天中午 12 点的值,只有第一天。
  • 尝试返回(st / end.values)
  • 如果我没有每天中午 12 点,那我就不能只为那一天提供 N/A 吗?这似乎是一种自然的输出。
  • 运行df.info()会得到什么?我在 iPython 中复制并运行了df = pd.read_clipboard();对我来说 df.info 显示 MultiIndex 而不是 DateTimeIndex...

标签: python datetime pandas time-series normalization


【解决方案1】:

这是我认为你想做的事。

将原始帧重新索引为包含范围内的所有日期。这确保 '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

这应该对您的输入范围和矢量化具有鲁棒性。但是我认为语法/易用性可以改进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2022-11-29
    • 2021-01-30
    • 1970-01-01
    • 2018-08-29
    • 2015-07-23
    相关资源
    最近更新 更多