按时间戳列过滤/选择熊猫数据帧的行
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)添加到时间戳列