按时间戳列过滤/选择熊猫数据帧的行

Posted

技术标签:

【中文标题】按时间戳列过滤/选择熊猫数据帧的行【英文标题】:filter/select rows of pandas dataframe by timestamp column 【发布时间】:2015-06-20 00:22:57 【问题描述】:

我是熊猫新手。我有两列 dt(日期时间戳)和值的数据框。

给定两个开始和结束数据时间戳:有没有一种简单的方法可以从包含两个日期时间戳之间的行的原始数据框创建一个新的数据框?

                dt    value
84    7/23/2014 7:00  0.300
85    7/23/2014 7:05  0.300
86    7/23/2014 7:10  0.312
87    7/23/2014 7:15  0.300
88    7/23/2014 7:20  0.300
89    7/23/2014 7:25  0.300
90    7/23/2014 7:30  0.300
91    7/23/2014 7:35  0.300
92    7/23/2014 7:40  0.300
93    7/23/2014 7:45  0.216
94    7/23/2014 7:50  0.204
95    7/23/2014 7:55  0.228
96    7/23/2014 8:00  0.228
97    7/23/2014 8:05  0.228
98    7/23/2014 8:10  0.228
99    7/23/2014 8:15  0.240
100   7/23/2014 8:20  0.228
101   7/23/2014 8:25  0.216
102   7/23/2014 8:30  0.228
103   7/23/2014 8:35  0.324
104   7/23/2014 8:40  0.336
105   7/23/2014 8:45  0.324
106   7/23/2014 8:50  0.324
107   7/23/2014 8:55  0.324
108   7/23/2014 9:00  0.252
109   7/23/2014 9:05  0.252
110   7/23/2014 9:10  0.240
111   7/23/2014 9:15  0.240
112   7/23/2014 9:20  0.252
113   7/23/2014 9:25  0.240
..               ...    ...
198  7/23/2014 16:30  0.132
199  7/23/2014 16:35  0.120
200  7/23/2014 16:40  0.180
201  7/23/2014 16:45  0.216
202  7/23/2014 16:50  0.204
203  7/23/2014 16:55  0.192

【问题讨论】:

【参考方案1】:

只要 dt 已经是 datetime dtype,您就可以使用日期字符串进行过滤,如果不是,那么您可以这样做:

df['dt'] = pd.to_datetime(df['dt'])

然后过滤:

In [115]:

df[(df['dt'] > '2014-07-23 07:30:00') & (df['dt'] < '2014-07-23 09:00:00')]
Out[115]:
                       dt  value
index                           
91    2014-07-23 07:35:00  0.300
92    2014-07-23 07:40:00  0.300
93    2014-07-23 07:45:00  0.216
94    2014-07-23 07:50:00  0.204
95    2014-07-23 07:55:00  0.228
96    2014-07-23 08:00:00  0.228
97    2014-07-23 08:05:00  0.228
98    2014-07-23 08:10:00  0.228
99    2014-07-23 08:15:00  0.240
100   2014-07-23 08:20:00  0.228
101   2014-07-23 08:25:00  0.216
102   2014-07-23 08:30:00  0.228
103   2014-07-23 08:35:00  0.324
104   2014-07-23 08:40:00  0.336
105   2014-07-23 08:45:00  0.324
106   2014-07-23 08:50:00  0.324
107   2014-07-23 08:55:00  0.324

【讨论】:

【参考方案2】:

上面的答案是对的,但是对于像我一样在这个问题发布超过 5 年后偶然发现这个问题的人,我想添加这句话。

如果你想过滤一个排好序的列(并且时间戳往往是一个),使用 pandas Series 的 searchsorted 函数来达到 O(log(n)) 复杂度而不是 O(n )。

下面的示例给出的结果差异远大于 1000 倍。由于复杂性的差异,这种差异可以任意大,但选择的数字是我在偶然发现时使用的数字关于这个问题。

import pandas as pd
import numpy as np
import timeit

N = 500000
M = 200

data = np.hstack([np.arange(0.,N).reshape(N,1),np.random.randn(N,M-1)])
df = pd.DataFrame(data,columns=["column"+str(i) for i in range(M)])

def return_first(df):
    return df[(df['column0'] > 100.5) & (df['column0'] < 400000.5)]

def return_second(df):
    t1 = df['column0'].searchsorted(100.5)
    t2 = df['column0'].searchsorted(400000.5)
    return df.loc[t1:t2-1]


if __name__ == '__main__':
    t = timeit.timeit(lambda: return_first(df), number=100)
    print(t)
    t = timeit.timeit(lambda: return_second(df), number=100)
    print(t)

结果:

59.1751627
0.015401400000001786

【讨论】:

我偶然发现了这个答案!我有一个排序的数据框,这就是我想要的。有没有一种简单的方法可以根据分钟/小时过滤掉?可以说我想得到在小时标记发生的一切。所以时间是 X:00:00 。 如果我正确理解依赖于数据的问题。如果它像问题中的那样非常结构化,您可以执行类似 df.loc[t1::288] 之类的操作(其中 t1 是第一个标记,一天中有 288 个 5 分钟间隔。如果数据不是那么结构化它变得更难,也许经过良好猜测后的二进制搜索风格算法可能是有益的。但在非常非结构化数据的情况下,要获得比第一个答案更高的效率变得越来越难。 谢谢!我最终做了类似 df.opentime.dt.minute == 0

以上是关于按时间戳列过滤/选择熊猫数据帧的行的主要内容,如果未能解决你的问题,请参考以下文章

Redshift - 将时区偏移量(Varchar)添加到时间戳列

大熊猫在grouby之后按日期时间过滤

如何从熊猫数据框中的时间戳列中删除时区

Python Pandas:每周列(int)到时间戳列转换(以周为单位)

按条件过滤大熊猫

使用实体框架按时间戳列选择新记录