提取时间戳的部分内容

时间:2013-02-22 07:49:45

标签: r postgresql

我有一些数据集,其中动物每隔5秒被记录一次。数据存储在postgis中,我使用R来分析和绘制数据。我想在图上刊登一些显示每小时位置的标记。我将数据集的子集拉到R中,使数据框中包含每个点的时间戳和x和y坐标。

我的数据集的summary()的一部分(总共大约10000行):

 id             datetime                        date           
Min.   :2664295   Min.   :2009-08-21 05:00:04   Min.   :2009-08-21  
1st Qu.:2666819   1st Qu.:2009-08-21 08:30:15   1st Qu.:2009-08-21  
Median :2669342   Median :2009-08-21 12:00:03   Median :2009-08-21  
Mean   :2669342   Mean   :2009-08-21 11:30:10   Mean   :2009-08-21  
3rd Qu.:2671866   3rd Qu.:2009-08-21 14:22:44   3rd Qu.:2009-08-21  
Max.   :2674390   Max.   :2009-08-21 16:59:58   Max.   :2009-08-21  

 lokalitet             cowid           x                y          
Length:10          Min.   :553   Min.   :455329   Min.   :6712350  
Class :character   1st Qu.:553   1st Qu.:455718   1st Qu.:6712744  
Mode  :character   Median :553   Median :456154   Median :6713068  
                   Mean   :553   Mean   :456011   Mean   :6713074  
                   3rd Qu.:553   3rd Qu.:456274   3rd Qu.:6713470  
                   Max.   :553   Max.   :456361   Max.   :6713596  

所以,我想做的是将日期时间的数据集子集,其中分钟部分为0,第二部分为< 5(即对于摘要中显示的时间戳我希望05:00:04和12:00:03。(我知道我可以在postgres中执行此操作,但因为基本数据集非常大(大约4 M行) )并且我没有对部分时间戳做出索引,我认为在R中的子集上执行此操作可能更好(并且没有,因为我想多次这样做,我不想只是手动查找第一行匹配,然后从那里获取每一个第720行)

3 个答案:

答案 0 :(得分:8)

使用lubridate包,可以很容易地从日期中提取分钟和秒,然后对它们进行测试。例如:

library(lubridate)

## Sample data
dates <- as.POSIXlt(c("2009-08-21 05:00:04","2009-08-21 08:30:15","2009-08-21 12:00:03","2009-08-21 11:30:10","2009-08-21 14:22:44","2009-08-21 16:59:58"))

## How to extract minutes
minute(dates)
# [1]  0 30  0 30 22 59

## How to extract seconds
second(dates)
# [1]  4 15  3 10 44 58

## Select dates from minutes and seconds values
dates[minute(dates)==0 & second(dates) < 5]
# [1] "2009-08-21 05:00:04" "2009-08-21 12:00:03"

答案 1 :(得分:2)

你可以创建一个带有格式字符串并转换为数字的辅助函数。我假设数据时间是POSIXct而不是POSIXlt。 (POSIXct不能很好地处理数据帧操作。)

ndtfrm <- function(dt, frm) as.numeric(format(dt, frm))
ndtfrm(dates, "%M")
#[1]  0 30  0 30 22 59
ndtfrm(dates, "%S")
#[1]  4 15  3 10 44 58

 dfrm[ ndtfrm(dfrm$dates, "%M") ==0 & ndtfrm(dfrm$dates, "%S") < 5 , ]

答案 2 :(得分:0)

感谢您的回答,但事实证明,在postgres中这样做最容易......

一个简单的

SELECT ..., case when extract(second from datetime)<5 
                         and extract(minute from datetime) = 28 
  then extract(hour from datetime) end as marker  FROM ....

给了我所需要的东西 - 因为我只是将这些数据与其他数据集一起处理,所以不需要搜索这些点。