[英]Translating time stamps (start, end) into time series data. Errors with align.time() and colnames
我是R的新手,但在參加了一個介紹課程並稍微玩了一下后,我希望它可以1)更優雅地解決我的建模目標(與Excel相比,這是我的備份計划)和2)是一個有用的技能可以帶走這個項目。
任務/目標:
我正在嘗試使用駕駛日記數據來模擬和模擬電動汽車的潛在能源和溫室氣體排放。 特別:
該類型的輸出,我想: 注意:這個輸出是不相關的下面提供的樣本數據。 我用某些理論旅行的某一天的前十分鍾作為例子
對於這個問題不是必不可少的,但可能有用的知道:我將使用上面的輸出交叉引用其他特定於驅動程序的數據,以根據與該行程相關的事物計算汽油(或電力)的逐分鍾消耗,如停車位置或行程距離。 我想在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”等填充任何駕駛時段,然后對所有得到的x數據幀進行求和/合並,並最終得到理想的結果。
不幸的是,當我試圖重復這個...
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)
我收到以下錯誤:
- UseMethod中的錯誤(“align.time”):沒有適用於'align.time'的方法應用於類“Date”的對象
colnames<-
錯誤colnames<-
(*tmp*
,value = c(“A.1”,“A.2”,“A.3”,“B.1”,“B.2”,:嘗試設置'colnames' '在尺寸小於兩維的物體上
我的out2代碼出了什么問題?
我還可以了解其他更好的解決方案或套餐嗎?
我意識到這可能是一種非常迂回的方式來達到我想要的輸出。
任何幫助將非常感激。
在此解決方案中,我讀取您的原始數據並對其進行格式化以獲取我之前答案的生成數據。 所提供的數據僅限於駕駛員的22次旅行,但此處的重塑不受行程次數的限制。 這個想法類似於用於生成樣本數據的想法。 我正在使用data.table
因為它可以方便地操作每組數據。
因此,對於每個(日,司機),我執行以下操作:
這是我的代碼:
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
一個想法是創建數據的熱圖(至少每天)以獲得一些直覺並查看重疊的驅動程序。 這里有兩種使用lattice
和ggplot2
但首先我將使用reshape2
以長格式reshape2
library(reshape2)
dat.m <- melt(dat,id.vars=c('id','day'))
然后我繪制我的熱圖以查看哪些驅動程序與其他驅動程序重疊,例如:
library(lattice)
levelplot(value~as.numeric(variable)*factor(id),data=dat.m)
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")
這不是您問題的答案。 老實說,我不清楚您在圖像中顯示的數據與數據示例之間的轉換。 好像你無法重現這些數據。 所以這是一個生成數據可重現示例的函數。 我認為驗證您的模型至少是有用的。
library(reshape2)
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')
## function to generate a trip sample
## min.dur : minimal duration of a trip
## max.dur : maximal duration of a trip
## min.trip : minimal number of trips that a user can do
gen.Trip <- function(min.dur=3,max.dur=10,min.trip=100){
## gen number of trip
n.trip <- sample(seq(min.trip,20),1)
## for each trip generate the durations
durations <- rep(seq(1,n.trip),
times=sample(seq(min.dur,max.dur),
max(min.dur,n.trip),rep=TRUE))
## generate a vector of positions
rr <- rle(durations)
mm <- cumsum(rr$lengths)
## idrty part here
pos <- sort(sample(seq(1,length(hours.min)-2*max(mm)),
n.trip,rep=FALSE)) + mm
## assign each trip to each posistion
val <- vector(mode='integer',length(hours.min))
for(x in seq_along(pos))
val[seq(pos[x],length.out=rr$len[x])] <- rr$val[x]
val
}
set.seed(1234)
nb.drivers <- 100
res <- replicate(nb.drivers,gen.Trip(),simplify=FALSE)
res <- do.call(rbind,res)
colnames(res) <- hours.min
rownames(res) <- paste0('driv',seq(nb.drivers))
head(res[,10:30])
## 00:09 00:10 00:11 00:12 00:13 00:14 00:15 00:16 00:17 00:18 00:19
## driv1 0 0 0 0 0 0 1 1 1 1 1
## driv2 0 1 1 1 1 1 1 2 2 2 1
## driv3 0 0 0 0 0 0 0 0 0 0 0
## driv4 1 1 1 0 0 0 0 0 0 0 0
## driv5 0 0 0 0 0 0 0 0 0 0 1
## driv6 0 0 0 0 0 0 0 0 0 0 0
## 00:20 00:21 00:22 00:23 00:24 00:25 00:26 00:27 00:28 00:29
## driv1 1 1 0 0 2 2 2 2 2 2
## driv2 0 0 0 0 0 0 3 3 3 3
## driv3 0 0 0 0 0 0 0 0 0 0
## driv4 0 0 0 0 0 0 0 0 0 0
## driv5 1 1 1 1 1 1 1 1 0 0
## driv6 0 0 0 0 0 0 0 0 0 0
res.m <- melt(res)
head(res.m)
## Var1 Var2 value
## 1 driv1 00:00 0
## 2 driv2 00:00 0
## 3 driv3 00:00 0
## 4 driv4 00:00 0
## 5 driv5 00:00 0
## 6 driv6 00:00 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.