3

我有一些数据集,其中每 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 行)

4

3 回答 3

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"
于 2013-02-22T08:12:59.083 回答
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 , ]
于 2013-02-22T10:48:59.867 回答
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 ....

给了我我需要的东西——因为我只是将这些数据与数据集的其余部分结合起来,所以没有必要搜索这些点。

于 2013-02-25T08:06:18.510 回答