python - 获取时间戳在不规则时间间隔内的行 pandas (Time Series)

标签 python pandas datetime time-series resampling

假设我有一个这样的数据框:

>>> i = pd.to_datetime(np.random.randint(time.time(), time.time()+10000, 15), unit='ms').sort_values()
>>> df = pd.DataFrame({'A':range(15),'B':range(10,40,2),'C':range(10,55,3)},index = i)
>>> df
                          A   B   C
1970-01-19 05:31:36.629   0  10  10
1970-01-19 05:31:36.710   1  12  13
1970-01-19 05:31:37.779   2  14  16
1970-01-19 05:31:38.761   3  16  19
1970-01-19 05:31:39.520   4  18  22
1970-01-19 05:31:39.852   5  20  25
1970-01-19 05:31:39.994   6  22  28
1970-01-19 05:31:41.370   7  24  31
1970-01-19 05:31:41.667   8  26  34
1970-01-19 05:31:42.515   9  28  37
1970-01-19 05:31:42.941  10  30  40
1970-01-19 05:31:43.037  11  32  43
1970-01-19 05:31:43.253  12  34  46
1970-01-19 05:31:43.333  13  36  49
1970-01-19 05:31:44.135  14  38  52

我想要的是:

                          A   B   C
1970-01-19 05:31:37.779   2.0  14.0  16.0   #last value within 2000 milli-sec interval from 05:31:36
1970-01-19 05:31:38.761   3.0  16.0  19.0      ##last value from the ^ value within 1000 msec interval
1970-01-19 05:31:39.994   6.0  22.0  28.0   #last value within 2000 milli-sec interval from 05:31:38
1970-01-19 05:31:39.994   6.0  22.0  28.0     *##last value from the ^ value within 1000 msec interval
1970-01-19 05:31:41.667   8.0  26.0  34.0   #last value within 2000 milli-sec interval from 05:31:40
1970-01-19 05:31:42.515   9.0  28.0  37.0      ##last value from the ^ value within 1000 msec interval
1970-01-19 05:31:43.333  13.0  36.0  49.0   #last value within 2000 milli-sec interval from 05:31:42
1970-01-19 05:31:44.135  14.0  38.0  52.0      ##last value from the ^ value within 1000 msec interval

我可以使用以下代码实现标有 # 的行:

>>> df.resample('2000ms').ffill().dropna(axis=0)
                        A     B     C
1970-01-19 05:31:38   2.0  14.0  16.0
1970-01-19 05:31:40   6.0  22.0  28.0
1970-01-19 05:31:42   8.0  26.0  34.0
1970-01-19 05:31:44  13.0  36.0  49.0

# note I do not care about how the timestamps are getting printed, I just want the correct values.

我找不到可以提供所需输出的 ​​pandas 解决方案。我可以用两个数据帧来做到这一点,一个在 2000ms 采样,另一个在 1000ms 采样,然后可能循环,并相应地插入。

问题是,我的数据的实际大小非常大,超过 4000000 行和 52 列。如果可以避免两个 dfs 或循环,我肯定会接受它。

注意:*标记的行会重复,因为在距离最后一个值的1000ms时间间隔内没有数据,所以最后看到的值会重复。对于 2000 毫秒的时间间隔也应该发生同样的情况。

如果可能,请告诉我一个方法...谢谢!

编辑:根据John Zwinck's comment编辑:

import datetime
def last_time(time):
    time = str(time)
    start_time = datetime.datetime.strptime(time[11:],'%H:%M:%S.%f')
    end_time = start_time + datetime.timedelta(microseconds=1000000)
    tempdf = df.between_time(*pd.to_datetime([str(start_time),str(end_time)]).time).iloc[-1]
    return tempdf
df['timestamp'] = df.index
df2 = df.resample('2000ms').ffill().dropna(axis=0)
df3 = df2.apply(lambda x:last_time(x['timestamp']), axis = 1)

pd.concat([df2, df3]).sort_index(kind='merge')

这给出:

                        A     B     C               timestamp
1970-01-19 05:31:38   2.0  14.0  16.0 1970-01-19 05:31:37.779
1970-01-19 05:31:38   3.0  16.0  19.0 1970-01-19 05:31:38.761
1970-01-19 05:31:40   6.0  22.0  28.0 1970-01-19 05:31:39.994
1970-01-19 05:31:40   6.0  22.0  28.0 1970-01-19 05:31:39.994
1970-01-19 05:31:42   8.0  26.0  34.0 1970-01-19 05:31:41.667
1970-01-19 05:31:42   9.0  28.0  37.0 1970-01-19 05:31:42.515
1970-01-19 05:31:44  13.0  36.0  49.0 1970-01-19 05:31:43.333
1970-01-19 05:31:44  14.0  38.0  52.0 1970-01-19 05:31:44.135

没关系,除了应用部分需要很长时间!


为了更容易复制:

,A,B,C
1970-01-19 05:31:36.629,0,10,10
1970-01-19 05:31:36.710,1,12,13
1970-01-19 05:31:37.779,2,14,16
1970-01-19 05:31:38.761,3,16,19
1970-01-19 05:31:39.520,4,18,22
1970-01-19 05:31:39.852,5,20,25
1970-01-19 05:31:39.994,6,22,28
1970-01-19 05:31:41.370,7,24,31
1970-01-19 05:31:41.667,8,26,34
1970-01-19 05:31:42.515,9,28,37
1970-01-19 05:31:42.941,10,30,40
1970-01-19 05:31:43.037,11,32,43
1970-01-19 05:31:43.253,12,34,46
1970-01-19 05:31:43.333,13,36,49
1970-01-19 05:31:44.135,14,38,52

最佳答案

您现有代码中较慢的部分是创建 df3,因此我将对其进行优化。

首先,请注意您的last_time(x) 函数查找从 x 到 x + 1 秒的时间范围内的最后一条记录。

不使用循环,我们可以从偏移整个向量中的时间开始:

end_times = df2.timestamp + datetime.timedelta(microseconds=1000000)

然后我们可以使用 numpy.searchsorted()(一个被高度低估的函数!)在 df 中搜索那些时间:

idx = np.searchsorted(df.timestamp, end_times)

顺便说一句,df.timestamp.searchsorted(end_times) 做同样的事情。

最后,请注意,这些生成的索引中的每一个都在我们想要的之后(我们不想要 1 秒后的值,我们想要之前的值):

df3a = df.iloc[idx - 1]

除了索引没有向下舍入外,这与您的 df3 得到相同的结果,因此只需替换它:

df3a.index = df2.index

这与您的 df3 完全相同,但计算速度更快。

关于python - 获取时间戳在不规则时间间隔内的行 pandas (Time Series),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59113957/

相关文章:

python - 使用 Python pandas,我如何创建一个函数来计算代表比前一行更低值的行的比例?

python - 将滚动平均值应用于列时如何填充第一个 N/A 单元格-python

php - 为不同时区的用户存储特定的日期/时间值

python - GAE "No module named urllib"

java - 如何发现给定接口(interface)背后的 NAT 类型

python - 填充具有重复值的索引中的缺失值

python - DataFrame 不允许时间戳转换以进行重采样

python - Pandas 可以在不修改文件其余部分的情况下读取和修改单个 Excel 文件工作表(选项卡)吗?

python - Ubuntu - 在 python : "ImportError: No module named mxnet" 中运行程序时出错

datetime - 将日期时间字符串解析为 rust chrono 中的本地时间