r - 将时间戳(开始、结束)转换为时间序列数据。 align.time() 和 colname 错误

标签 r time time-series xts

我是 R 新手,但在学习了入门类(class)并稍微使用了一下之后,我希望它能够 1)更优雅地解决我的建模目标(与 Excel 相比,这是我的备用计划)和 2 )是从这个项目中学到的有用技能。

任务/目标:

我正在尝试使用驾驶日记数据来模拟和建模电动汽车的势能和温室气体排放。具体来说:

  1. 我有驾驶日记数据(开始和结束时间戳,以及数千名驾驶员的其他数据 - 下面的基本示例),我想将其转换为:
  2. 24 小时时间序列数据,这样在 24 小时期间的每一分钟,我都能准确地知道谁在驾驶车辆,以及该车辆属于哪个“行程”(对于该驾驶员而言)。我这里的问题就集中在这个问题上。

我想要的输出类型: 注意:此输出与下面提供的示例数据相关。我用某天的前十分钟进行一些理论旅行只是作为例子

enter image description here

对于这个问题来说不是必需的,但了解一下可能会很有用:我将使用上面的输出来交叉引用其他特定于驾驶员的数据,以根据与以下内容相关的内容来计算每分钟的汽油(或电力)消耗量该行程,例如 parking 位置或行程距离。我想在 R 中执行此操作,但在继续这一步之前必须首先弄清楚上述问题。

我到目前为止的解决方案基于:

问题:

简化数据示例:

a <- c("A","A","A","B","B","B","C","C","C")
b <- c(1, 2, 3, 1, 2, 3, 1, 2, 3)
c <- as.POSIXct(c(0.29167, 0.59375, 0.83333, 0.45833, 0.55347, 0.27083, 0.34375, 0.39236, 0.35417)*24*3600 + as.POSIXct("2013-1-1 00:00") )
d <- as.POSIXct(c(0.334027778, 0.614583333, 0.875, 0.461805556, 0.563888889, 0.295138889, 0.375, 0.503472222, 0.364583333)*24*3600 + as.POSIXct("2013-1-1 00:00"))
e <- c(2, 8, 2, 5, 5, 2, 5, 5, 2)
f <- as.POSIXct(c(0, 0.875, 0, 0.479166666666667, 0.580555555555556, 0.489583333333333, 0.430555555555556, 0.541666666666667, 0.711805555555555)*24*3600 + as.POSIXct("2013-1-1 00:00"))
g <- as.POSIXct(c(0, 0.885, 0, 0.482638888888889, 0.588194444444444, 0.496527777777778, 0.454861111111111, 0.559027777777778, 0.753472222222222)*24*3600 + as.POSIXct("2013-1-1 00:00"))
h <- c(0, 1, 0, 1, 4, 8, 8, 1, 5)
i <- as.POSIXct(c(0, 0, 0, 0.729166666666667, 0.595833333333333, 0.534722222222222, 0.59375, 0.779861111111111, 0.753472222222222)*24*3600 + as.POSIXct("2013-1-1 00:00"))
j <- as.POSIXct(c(0, 0, 0, 0.736111111111111, 0.605555555555556, 0.541666666666667, 0.611111111111111, 0.788194444444445, 0.75625)*24*3600 + as.POSIXct("2013-1-1 00:00"))
k <- c(0, 0, 0, 4, 4, 2, 5, 8,1)
testdata <- data.frame(a,b,c,d,e,f,g,h,i,j,k)
names(testdata) <- c("id", "Day", "trip1_start", "trip1_end", "trip1_purpose", "trip2_start", "trip2_end", "trip2_purpose", "trip3_start", "trip3_end", "trip3_purpose")

在此示例数据中,我有三个司机(id = A、B、C),每个司机在三个不同的日子(天 = 1、2、3)开车。请注意,某些司机的行程次数可能不同。时间戳表示驾驶事件的开始和结束时间。

然后,我创建一整天(2013 年 1 月 1 日)的分钟间隔

start.min <- as.POSIXct("2013-01-01 00:00:00 PST")
end.max <- as.POSIXct("2013-01-01 23:59:59 PST")
tinterval <- seq.POSIXt(start.min, end.max, na.rm=T, by = "mins")

在给定用户驾驶的分钟内插入“1”:

out1 <- xts(,align.time(tinterval,60))
# loop over each user
for(i in 1:NROW(testdata)) {
  # paste the start / end times into an xts-style range
  timeRange <- paste(format(testdata[i,c("trip1_start","trip1_end")]),collapse="/")
  # add the minute "by parameter" for timeBasedSeq
  timeRange <- paste(timeRange,"M",sep="/")
  # create the by-minute sequence and align to minutes to match "out"
  timeSeq <- align.time(timeBasedSeq(timeRange),60)
  # create xts object with "1" entries for times between start and end
  temp1 <- xts(rep(1,length(timeSeq)),timeSeq)
  # merge temp1 with out and fill non-matching timestamps with "0"
  out1 <- merge(out1, temp1, fill=0)
}
# add column names
colnames(out1) <- paste(testdata[,1], testdata[,2], sep = ".")

我们的想法是在每次旅行时重复此操作,例如out2、out3 等,其中我会用“2”、“3”等填充任何驾驶周期,然后求和/合并所有生成的 outx 数据帧,并最终获得所需的结果结果。

不幸的是,当我尝试对 out2 重复此操作时...

out2 <- xts(,align.time(tinterval,60))
for(i in 1:NROW(testdata)) {
  timeRange2 <- paste(format(testdata[i,c("trip2_start","trip2_end")]),collapse="/")
  timeRange2 <- paste(timeRange2,"M",sep="/")
  timeSeq2 <- align.time(timeBasedSeq(timeRange2),60)
  temp2 <- xts(rep(2,length(timeSeq2)),timeSeq2)
  out2 <- merge(out2, temp2, fill=0)
}
colnames(out2) <- paste(testdata[,1], testdata[,2], sep = ".")
head(out2)

我收到以下错误:

  • Error in UseMethod("align.time") : no applicable method for 'align.time' applied to an object of class "Date"
  • Error in colnames<-(*tmp*, value = c("A.1", "A.2", "A.3", "B.1", "B.2", : attempt to set 'colnames' on an object with less than two dimensions

我的 out2 代码有什么问题?

还有其他更好的解决方案或软件包我可以了解吗?

我意识到这可能是达到我想要的输出的一种非常迂回的方式。

任何帮助将不胜感激。

最佳答案

在此解决方案中,我读取您的原​​始数据并将其格式化以获取我之前答案的生成数据。提供的数据仅限于驾驶员的22次行程,但这里的 reshape 不受行程次数的限制。这一想法与用于生成样本数据的想法类似。我使用 data.table 因为它可以方便地操作每个组的数据。

因此,对于每一天(一天,驾驶员)我都会执行以下操作:

  1. 创建一个长度为分钟数的零向量
  2. 使用 XXXstrip_start 和 XXXstrip_end 读取开始和结束位置。
  3. 创建序列 seq(start,end)
  4. 使用此序列按数字序列更改零

这是我的代码:

start.min <- as.POSIXct("2013-01-01 00:00:00 PST")
hours.min <- format(seq(start.min, 
                        length.out=24*60, by = "mins"),
                    '%H:%M')
library(data.table)
diary <- read.csv("samplediary.csv",
                  stringsAsFactors=FALSE)
DT <- data.table(diary,key=c('id','veh_assigned','day'))

dat <- DT[, as.list({ .SD;nb.trip=sum_trips
           tripv <- vector(mode='integer',length(hours.min))
           if(sum_trips>0){
             starts = mget(paste0('X',seq(nb.trip),'_trip_start'))
             ends = mget(paste0('X',seq(nb.trip),'_trip_end'))
             ids <- mapply(function(x,y){
                                        seq(as.integer(x),as.integer(y))},
                           starts,ends,SIMPLIFY = FALSE)
             for (x in seq_along(ids))tripv[ids[[x]]] <- x
             }
            tripv
           }),
   by=c('id','day')]
setnames(x=dat,old=paste0('V',seq(hours.min)),hours.min)

如果您对前 10 个变量进行子集化,您会得到以下结果:

dat[1:10,1:10,with=FALSE]


       id day 00:00 00:01 00:02 00:03 00:04 00:05 00:06 00:07
 1: 3847339   1     0     0     0     0     0     0     0     0
 2: 3847384   1     0     0     0     0     0     0     0     0
 3: 3847436   1     0     0     0     0     0     0     0     0
 4: 3847439   1     0     0     0     0     0     0     0     0
 5: 3847510   1     0     0     0     0     0     0     0     0
 6: 3847536   1     0     0     0     0     0     0     0     0
 7: 3847614   1     0     0     0     0     0     0     0     0
 8: 3847683   1     0     0     0     0     0     0     0     0
 9: 3847841   1     0     0     0     0     0     0     0     0
10: 3847850   1     0     0     0     0     0     0     0     0

一个想法是创建数据热图(至少每天)以获得一些直觉并查看重叠的驱动因素。这里有两种使用latticeggplot2来做到这一点的方法,但首先我将使用reshape2

以长格式 reshape 数据
library(reshape2)
dat.m <- melt(dat,id.vars=c('id','day'))

然后,我绘制热图来查看哪些驱动程序与其他驱动程序重叠,例如:

library(lattice)
levelplot(value~as.numeric(variable)*factor(id),data=dat.m)

enter image description here

library(ggplot2)
ggplot(dat.m, aes(x=as.numeric(variable),y=factor(id)))+ 
        geom_tile(aes(fill = value)) +
  scale_fill_gradient(low="grey",high="blue")

enter image description here

关于r - 将时间戳(开始、结束)转换为时间序列数据。 align.time() 和 colname 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17363194/

相关文章:

r - corAR1 上 gls 的 r 错误 - 不是唯一的

r - 找到字符串中最长的连续元音集

r - R 中缺失分类值和数值的聚类算法

ubuntu - Bitnami GitLab(ubuntu)服务器无法同步时间

python - pandas dataframe将函数应用于具有nans的列

r - 如何以 x 分钟的间隔计算属于某一特定列的唯一标签的数量(与时间戳相关)?

java - 针对使用 LocalDateTime 的 api 进行测试

java - 比较 System.currentTimeMillis()

python - Pandas :从一行创建多行 'dummy data'

python - 计算一天中每分钟数据帧中有多少行为 "active"的最有效方法是什么?