我有一个相当直接的问题,我希望以比我目前更高的效率解决这个问题。
我有一堆数据作为一组监控指标进入。输入数据结构为元组数组。每个元组都是(时间戳,值)。时间戳是整数纪元秒,值是正常浮点数。示例:
inArr = [ (1388435242, 12.3), (1388435262, 11.1), (1388435281, 12.8), ... ]
时间戳并不总是相同的秒数,但它通常是接近的。有时我们会提交重复的数字,有时我们会错过数据点等。
我当前的解决方案采用时间戳和:
输出数据必须采用以下格式:
outArr = [ (startTime, timeStep, numVals), [ val1, val2, val3, val4, ... ] ]
我怀疑这是Python Pandas http://pandas.pydata.org/(或Numpy / SciPy)解决的问题。
是的,我的解决方案有效,但是当我在60K数据点上运行时,可能需要十分之一秒(或更长时间)才能运行。当我尝试处理大量数量的数据集时,这很麻烦。
所以,我正在寻找一种可能比我的纯Python版本运行得更快的解决方案。我想我(根据之前与Argonne国家实验室人员的几次谈话)假设SciPy和Numpy在阵列操作中“稍微快一点”。我在Pandas代码中看了一下(大约一个小时左右),但是做这组操作看起来很麻烦。我不对吗?
- 编辑以显示预期输出 -
数据点之间的中间时间是20秒,一半是10秒。为了确保我们在时间戳之间放置线条,我们将开始时间设置在第一个数据点之前10秒。如果我们只是将开始时间作为第一个时间戳,那么我们在一个时间间隔内获得2个时间戳的可能性要大得多。
所以,1388435242 - 10 = 1388435232.时间步长是中位数,20秒。这里的数字是3。
outArr = [ (1388435232, 20, 3), [ 12.3, 11.1, 12.8 ] )
这是Graphite在绘制输出图形时所期望的格式;这不是我的发明。但是,将时间序列数据放在这种格式中似乎很常见 - 开始时间,间隔,然后是数组数组。
答案 0 :(得分:3)
这是草图
创建输入系列
In [24]: x = zip(pd.date_range('20130101',periods=1000000,freq='s').asi8/1000000000,np.random.randn(1000000))
In [49]: x[0]
Out[49]: (1356998400, 1.2809949462375376)
创建框架
In [25]: df = DataFrame(x,columns=['time','value'])
使日期有点随机(模拟一些数据)
In [26]: df['time1'] = df['time'] + np.random.randint(0,10,size=1000000)
将纪元秒转换为datetime64 [ns] dtype
In [29]: df['time2'] = pd.to_datetime(df['time1'],unit='s')
区分系列(创建timedeltas)
In [32]: df['diff'] = df['time2'].diff()
看起来像这样
In [50]: df
Out[50]:
time value time1 time2 diff
0 1356998400 -0.269644 1356998405 2013-01-01 00:00:05 NaT
1 1356998401 -0.924337 1356998401 2013-01-01 00:00:01 -00:00:04
2 1356998402 0.952466 1356998410 2013-01-01 00:00:10 00:00:09
3 1356998403 0.604783 1356998411 2013-01-01 00:00:11 00:00:01
4 1356998404 0.140927 1356998407 2013-01-01 00:00:07 -00:00:04
5 1356998405 -0.083861 1356998414 2013-01-01 00:00:14 00:00:07
6 1356998406 1.287110 1356998412 2013-01-01 00:00:12 -00:00:02
7 1356998407 0.539957 1356998414 2013-01-01 00:00:14 00:00:02
8 1356998408 0.337780 1356998412 2013-01-01 00:00:12 -00:00:02
9 1356998409 -0.368456 1356998410 2013-01-01 00:00:10 -00:00:02
10 1356998410 -0.355176 1356998414 2013-01-01 00:00:14 00:00:04
11 1356998411 -2.912447 1356998417 2013-01-01 00:00:17 00:00:03
12 1356998412 -0.003209 1356998418 2013-01-01 00:00:18 00:00:01
13 1356998413 0.122424 1356998414 2013-01-01 00:00:14 -00:00:04
14 1356998414 0.121545 1356998421 2013-01-01 00:00:21 00:00:07
15 1356998415 -0.838947 1356998417 2013-01-01 00:00:17 -00:00:04
16 1356998416 0.329681 1356998419 2013-01-01 00:00:19 00:00:02
17 1356998417 -1.071963 1356998418 2013-01-01 00:00:18 -00:00:01
18 1356998418 1.090762 1356998424 2013-01-01 00:00:24 00:00:06
19 1356998419 1.740093 1356998428 2013-01-01 00:00:28 00:00:04
20 1356998420 1.480837 1356998428 2013-01-01 00:00:28 00:00:00
21 1356998421 0.118806 1356998427 2013-01-01 00:00:27 -00:00:01
22 1356998422 -0.935749 1356998427 2013-01-01 00:00:27 00:00:00
计算中位数
In [34]: df['diff'].median()
Out[34]:
0 00:00:01
dtype: timedelta64[ns]
计算平均值
In [35]: df['diff'].mean()
Out[35]:
0 00:00:00.999996
dtype: timedelta64[ns]
应该让你入门
答案 1 :(得分:1)
您可以将inArr
传递给pandas Dataframe:
df = pd.DataFrame(inArr, columns=['time', 'value'])
df['time'].diff()
df['time'].diff().median()
对于其中的一些问题,可能会将您的秒数转换为datetime
并将其设置为索引:
In [39]: df['time'] = pd.to_datetime(df['time'], unit='s')
In [41]: df = df.set_index('time')
In [42]: df
Out[42]:
value
time
2013-12-30 20:27:22 12.3
2013-12-30 20:27:42 11.1
2013-12-30 20:28:01 12.8
然后要同时处理多个值,请使用groupby
。
In [49]: df.groupby(level='time').mean()
Out[49]:
value
time
2013-12-30 20:27:22 12.3
2013-12-30 20:27:42 11.1
2013-12-30 20:28:01 12.8
这是相同的,因为没有任何欺骗。
不确定你对最后两个的意思。
你想要的输出似乎与你之前想要的相反。您应该对具有相同时间戳的值进行平均,现在您想要它们全部?也许清楚一点。