考虑到你有一些不均匀的时间序列数据:
import pandas as pd
import random as randy
ts = pd.Series(range(1000),index=randy.sample(pd.date_range('2013-02-01 09:00:00.000000',periods=1e6,freq='U'),1000)).sort_index()
print ts.head()
2013-02-01 09:00:00.002895 995
2013-02-01 09:00:00.003765 499
2013-02-01 09:00:00.003838 797
2013-02-01 09:00:00.004727 295
2013-02-01 09:00:00.006287 253
假设我想在1毫秒的窗口内进行滚动操作以获得此结果:
2013-02-01 09:00:00.002895 995
2013-02-01 09:00:00.003765 499 + 995
2013-02-01 09:00:00.003838 797 + 499 + 995
2013-02-01 09:00:00.004727 295 + 797 + 499
2013-02-01 09:00:00.006287 253
目前,我把所有东西都重新投入了多头并在cython中做到了,但这在纯大熊猫中是否可行?我知道你可以做类似.asfreq('U')之类的东西,然后填充并使用传统的功能,但是当你拥有超过玩具行数时,这不会扩展。
作为参考,这是一个hackish,而不是快速的Cython版本:
%%cython
import numpy as np
cimport cython
cimport numpy as np
ctypedef np.double_t DTYPE_t
def rolling_sum_cython(np.ndarray[long,ndim=1] times, np.ndarray[double,ndim=1] to_add, long window_size):
cdef long t_len = times.shape[0], s_len = to_add.shape[0], i =0, win_size = window_size, t_diff, j, window_start
cdef np.ndarray[DTYPE_t, ndim=1] res = np.zeros(t_len, dtype=np.double)
assert(t_len==s_len)
for i in range(0,t_len):
window_start = times[i] - win_size
j = i
while times[j]>= window_start and j>=0:
res[i] += to_add[j]
j-=1
return res
在更大的系列中展示:
ts = pd.Series(range(100000),index=randy.sample(pd.date_range('2013-02-01 09:00:00.000000',periods=1e8,freq='U'),100000)).sort_index()
%%timeit
res2 = rolling_sum_cython(ts.index.astype(int64),ts.values.astype(double),long(1e6))
1000 loops, best of 3: 1.56 ms per loop
答案 0 :(得分:11)
您可以使用cumsum和二分查找来解决此类问题。
from datetime import timedelta
def msum(s, lag_in_ms):
lag = s.index - timedelta(milliseconds=lag_in_ms)
inds = np.searchsorted(s.index.astype(np.int64), lag.astype(np.int64))
cs = s.cumsum()
return pd.Series(cs.values - cs[inds].values + s[inds].values, index=s.index)
res = msum(ts, 100)
print pd.DataFrame({'a': ts, 'a_msum_100': res})
a a_msum_100
2013-02-01 09:00:00.073479 5 5
2013-02-01 09:00:00.083717 8 13
2013-02-01 09:00:00.162707 1 14
2013-02-01 09:00:00.171809 6 20
2013-02-01 09:00:00.240111 7 14
2013-02-01 09:00:00.258455 0 14
2013-02-01 09:00:00.336564 2 9
2013-02-01 09:00:00.536416 3 3
2013-02-01 09:00:00.632439 4 7
2013-02-01 09:00:00.789746 9 9
[10 rows x 2 columns]
您需要一种处理NaN的方法,根据您的应用程序,您可能需要滞后时间的主要值(即使用kdb + bin与np.searchsorted之间的差异)。
希望这有帮助。
答案 1 :(得分:6)
这是一个老问题,但对于那些从谷歌偶然发现这一点的人来说:在pandas 0.19中这是内置的功能
http://pandas.pydata.org/pandas-docs/stable/computation.html#time-aware-rolling
因此,要获得1毫秒的窗口,您可以通过
获得Rolling对象dft.rolling('1ms')
,总和将是
dft.rolling('1ms').sum()
答案 2 :(得分:0)
使用rolling_sum
可能更有意义:
pd.rolling_sum(ts, window=1, freq='1ms')
答案 3 :(得分:0)
这样的事情怎么样:
创建1 ms的偏移量:
In [1]: ms = tseries.offsets.Milli()
创建一系列与时间序列长度相同的索引位置:
In [2]: s = Series(range(len(ts)))
应用lambda函数,该函数为ts系列中的当前时间编制索引。该函数返回x - ms and x
之间所有ts条目的总和。
In [3]: s.apply(lambda x: ts.between_time(start_time=ts.index[x]-ms, end_time=ts.index[x]).sum())
In [4]: ts.head()
Out[4]:
2013-02-01 09:00:00.000558 348
2013-02-01 09:00:00.000647 361
2013-02-01 09:00:00.000726 312
2013-02-01 09:00:00.001012 550
2013-02-01 09:00:00.002208 758
以上功能的结果:
0 348
1 709
2 1021
3 1571
4 758