熊猫时间序列重新采样和插值

时间:2016-10-14 02:35:58

标签: pandas time-series interpolation python-3.5

我有时间戳传感器数据。由于技术细节,我每隔一分钟从大约的传感器获取数据。数据可能如下所示:

   tstamp               val
0  2016-09-01 00:00:00  57
1  2016-09-01 00:01:00  57
2  2016-09-01 00:02:23  57
3  2016-09-01 00:03:04  57
4  2016-09-01 00:03:58  58
5  2016-09-01 00:05:00  60

现在,基本上,如果我在确切的时间内获得所有数据,我会非常高兴,但我没有。保存分布并在每分钟获得数据的唯一方法是进行插值。例如,在行索引1和2之间有83秒,并且在精确分钟获取值的自然方式是在两行数据之间进行插值(在这种情况下,它是57,但事实并非如此)到处)。

现在,我的方法是执行以下操作:

date = pd.to_datetime(df['measurement_tstamp'].iloc[0].date())
ts_d = df['measurement_tstamp'].dt.hour * 60 * 60 +\
       df['measurement_tstamp'].dt.minute * 60 +\
       df['measurement_tstamp'].dt.second
ts_r = np.arange(0, 24*60*60, 60)
data = scipy.interpolate.interp1d(x=ts_d, y=df['speed'].values)(ts_r)
req = pd.Series(data, index=pd.to_timedelta(ts_r, unit='s'))
req.index = date + req.index

但这对我来说感觉相当漫长。有很好的熊猫方法可以进行重新采样,舍入等。我一整天都在阅读它们,但事实证明,没有什么能像我想要的那样进行插值。 resample的作用类似于groupby,并将平均时间点放在一起。 fillna进行插值,但在resample已经通过平均更改数据之后不进行插值。

我错过了什么,或者我的方法是最好的?

为简单起见,假设我按天和按传感器对数据进行分组,因此一次只插入一个传感器的24小时。

2 个答案:

答案 0 :(得分:6)

d = df.set_index('tstamp')
t = d.index
r = pd.date_range(t.min().date(), periods=24*60, freq='T')

d.reindex(t.union(r)).interpolate('index').ix[r]

enter image description here

注意,periods=24*60适用于每日数据,而不适用于问题中提供的示例。对于该示例,periods=6将起作用。

答案 1 :(得分:0)

5 年后,pandas 发生了一些变化(主要是 ix 函数已弃用)。无论如何,我已经重写了 piRSquared 的答案以使用当前的熊猫版本,并且还改进了答案的日期范围问题:

import pandas as pd
from datetime import datetime

df = pd.DataFrame({"tstamp": [
    datetime(2016, 9, 1, 0, 0, 0),
    datetime(2016, 9, 1, 0, 1, 0),
    datetime(2016, 9, 1, 0, 2, 23),
    datetime(2016, 9, 1, 0, 3, 4),
    datetime(2016, 9, 1, 0, 3, 58),
    datetime(2016, 9, 1, 0, 5, 0)], 
    "val": [57, 57, 57, 57, 58, 60]})


d = df.set_index('tstamp')
t = d.index

r = pd.date_range(t.min(), t.max(), freq='T')

d = d.reindex(t.union(r)).interpolate('index').loc[r]

d:

                           val
2016-09-01 00:00:00  57.000000
2016-09-01 00:01:00  57.000000
2016-09-01 00:02:00  57.000000
2016-09-01 00:03:00  57.000000
2016-09-01 00:04:00  58.064516
2016-09-01 00:05:00  60.000000