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

41

我是pandas的新手。我有一个包含两列dt(日期时间戳)和value的数据帧。

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

                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
3个回答

67
只要dt已经是datetime数据类型,您可以使用日期字符串进行过滤,否则您可以通过以下方式进行转换:
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

8

您也可以使用query功能:

In [25]: df.query('"2014-07-23 07:55:00" <= dt <= "2014-07-23 08:20:00"')
Out[25]: 
                     dt  value
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

我遇到了一个小问题:“无法比较时区未知和时区已知的日期时间对象”,但我通过以下方法解决了它:df.query('"2023-04-01 00:00:00.000Z" <= dt < "2024-10-01 00:00:00.000Z"')。 - R13mus

6
上面的答案是正确的,但对于像我这样在发布问题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。 - NewGuyInJava
1
如果我正确理解问题,那取决于数据。如果数据非常结构化,就像问题中的数据一样,您可以执行类似于df.loc[t1::288]的操作(其中t1是第一个标记,一天有288个5分钟间隔)。 如果数据不是那么结构化,那么变得更加困难,也许在猜测后进行二分搜索风格的算法可能会有益处。但是在非常不规则的数据情况下,要比第一个答案获得更高的效率变得越来越困难。 - DwightFromTheOffice
谢谢!我最终做了像 df.opentime.dt.minute == 0 这样的事情。 - NewGuyInJava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接