Yur*_*ers 7 datetime r time-series lubridate r-maptools
我正在分析由几个环境变量组成的复杂数据集中的时间模式以及来自各种动物物种的活动数据.这些数据已通过多个实验设置收集,每个设置的数据每分钟存储一次.该项目已经运行了几年,所以我的数据集相当大.
我的一个数据集的前几行看起来像这样:
> head(setup_01)
DateTime Film_number unused PIR Wheel Temperature LightOld LightDay LightNight LightUV IDnumbers error mouse shrew vole rat frog rest extra_info odour
1 2015-03-10 12:27:10 x 0 0 13.40 1471.34 -0.97 1331.29 700.42 no error 0 0 0 0 0 0 1
2 2015-03-10 12:28:10 x 0 0 13.43 1471.38 -1.07 1291.11 731.32 no error 0 0 0 0 0 0 1
3 2015-03-10 12:29:10 x 0 0 13.31 1471.24 -1.08 1368.57 1016.02 no error 0 0 0 0 0 0 1
Run Code Online (Sandbox Code Playgroud)
由于我想将这些变量与各个季节的日出和日落等各种自然循环联系起来,我已经利用这个包maptools来计算日出和日落时间
library(maptools)
gpclibPermit()
#set coordinates
crds=c(4.4900,52.1610)
# download the sunrise/sunset/etc data
setup_01$sunrise=sunriset(matrix(crds,nrow=1),dateTime=as.POSIXct(setup_01$DateTime),POSIXct.out=TRUE,direction="sunrise")
setup_01$sunset=sunriset(matrix(crds,nrow=1),dateTime=as.POSIXct(setup_01$DateTime),POSIXct.out=TRUE,direction="sunset")
#create a variable that's 0 except at sunrise, and one that's 0 except at sunset
setup_01$sunrise_act=0
setup_01$sunset_act=0
setup_01[abs(unclass(setup_01[,"DateTime"])-unclass(setup_01[,"sunrise"]$time))<30,]$sunrise_act=1
setup_01[abs(unclass(setup_01[,"DateTime"])-unclass(setup_01[,"sunset"]$time))<30,]$sunset_act=1
Run Code Online (Sandbox Code Playgroud)
由于大多数动物的行为不同,取决于它是白天还是黑夜,我使用日落/日出时间来计算一个新变量,即夜间0和白天1:
#create a variable that's 0 at night and 1 at daytime
setup_01$daytime=0
setup_01[setup_01[,"DateTime"]>setup_01[,"sunrise"]$time & setup_01[,"DateTime"]<setup_01[,"sunset"]$time,]$daytime=1
Run Code Online (Sandbox Code Playgroud)
到目前为止,这么好......甚至可以maptools使用民用/航海/天文黄昏和黎明的开始而不是日出和日落.
然而,这是我的问题开始的地方.我想在实验中记录所有的日子.而不是像往常那样在午夜增加日间计数器,我想在日落时增加日间计数器(或者可能在将来的实验中增加另一个可移动的时间,如日出,航海黄昏和黎明......) .由于日落并非每天都在同一时间发生,因此对我来说,这不是一个直截了当的问题.
我只想出一个for-loop,这不是一个很好的做事方式.另外,考虑到我在几个设置中每分钟收集一次超过6年的数据点,我可以坐下来观看构造板移动,而R贯穿一大堆这样的循环:
setup_01$day=0
day<-1
for(i in 1:nrow(setup_01)){
setup_01[i,]$day<-day
if(setup_01[i,]$sunset_act==1){
day<-day+1
}
}
Run Code Online (Sandbox Code Playgroud)
除了丑陋和缓慢之外,这段代码还有一个大问题:它不处理缺失的值.有时,由于设备故障,数据根本没有记录数小时或数天.如果在日落期间未记录任何数据,则上述代码不会增加日期计数器.这意味着我需要 - 不知何故 - 合并日期/时间代码.从实验开始以来,很容易创建一个天数变量:
setup_01$daynumber<-as.integer(ceiling(difftime(setup_01$DateTime, setup_01$DateTime[1], units = "days")))
Run Code Online (Sandbox Code Playgroud)
也许这些数字可以使用,可能会同Heroka的不错rle-algorithm.
我用dput做几个月的有价值的数据从一个菜单,包括丢失数据的几大块,以及新创建的变量(如在这篇文章中,并描述Heroka的答案)可用在这里.
我寻找的东西更好,更好,特别快,但一直无法想出一个好方法.我已经摆弄了我的数据框的子集,但得出的结论是它可能是一种愚蠢的方法.我已经看了maptools,lubridate和GeoLight.我搜索谷歌,堆栈溢出和各种书籍,像哈德利韦翰的梦幻般的预研.一切都无济于事.也许我错过了一些明显的东西.我希望有人可以帮助我.
我更喜欢基于预先计算表的解决方案。虽然速度较慢,但我发现它更容易理解。然后我用来dplyr安排我需要的信息。
让我表明我的意思。为了举例,我创建了一个日落时间列表。当然,你需要计算实际的值。
library(dplyr)
n.obs=1000
set.seed(10)
t0 <- as.POSIXct('2015-03-08 18:00:00')
artificial.sunsets <- data.frame(num.day= seq(0,n.obs+35)) %>% mutate(sunset=cumsum(rlnorm(length(num.day))*30)+t0 + 24*3600*num.day)
Run Code Online (Sandbox Code Playgroud)
artificial.sunsets包含天数和日落的确切时间,但也可能包括有关该天的更多信息。
还有一些人工数据:
t0 <- as.POSIXct('2015-03-10 12:27:10')
test.data <- data.frame(DateTime=t0+ seq(0, n.obs*24*3600, by=3600), observation=rnorm(24*n.obs+1))
Run Code Online (Sandbox Code Playgroud)
然后可以使用以下方法找到前一个日落:
find.sunset.before <- function(x){
cbind(x,artificial.sunsets %>% filter(sunset < x$DateTime) %>% tail(.,n=1))
}
data.with.sunset=test.data %>% rowwise() %>% do(find.sunset.before(.)) %>% ungroup()%>% mutate(rel.time = DateTime-sunset)
head(data.with.sunset)
Run Code Online (Sandbox Code Playgroud)
生成的表将包含另外三列:1) 相应的天数,2) 相应的日落时间,以及 3) 日落后的时间。
由于日期编号出现在另一个表中,因此这对于丢失测量值应该具有鲁棒性。您还可以轻松修改算法以使用不同的时间,甚至应用多个。
所有这些都可以使用 data.table 更快地完成:
library(data.table)
dt1 <- data.table(artificial.sunsets)
dt2 <- data.table(test.data)
dt1[,DateTime:=sunset]
setkey(dt1, DateTime)
setkey(dt2, DateTime)
r <- dt1[dt2,roll=TRUE]
r[,time.diff:=DateTime-sunset]
Run Code Online (Sandbox Code Playgroud)
我尝试用 system.time 计时 1000 个观察结果 - 前一个大约需要 1m,data.table 解决方案是 0.011s。
| 归档时间: |
|
| 查看次数: |
655 次 |
| 最近记录: |