(编辑:这里的问题之一是规模,即对于一行有用的东西会在200,000 * 50数据帧上爆炸/崩溃。例如,strptime必须按列方式应用,而不是按行方式应用于避免挂。 我正在寻找工作代码解决方案,你实际上在200,000 * 50上运行,包括你的测量运行时间,而不仅仅是偶然的“这很容易”的评论。很容易获得运行时> 12小时,如果你选错了fn。接下来,我还要求你让我的零时间调整代码更快,工作还没完成,直到完成。到目前为止没人试过。)
我希望矢量化并加速以下多步骤对数时间转换,精确到毫秒,包括将 strtime()
转换为单个数字,然后进行减法,然后log() (省略了200,000行* 300列;其他(非时间)列)。
代码如下。
除了使其矢量化和快速,一个额外的问题是我不确定如何最好地表示每一步(高维)中间值,例如作为strtime,matrix,vector的列表。我已经尝试了 apply,sapply,lapply,vapply,ddply::maply(),...
,但是中间格式的不兼容性一直让我搞砸了......
每行有50列 time1..time50 (chr,format =“HH:MM:SS.sss”),表示时间为字符串,以毫秒为单位。 I需要毫秒精度。
在每行中,列 time1..time50 的顺序不是递减,我希望将它们转换为 time50 之前的时间日志。转换fn parse_hhmmsecms()
位于底部,需要严格的矢量化和加速,您可以看到注释掉的替代版本。我到目前为止所知: strtime()
比(多个) substr()
调用更快,然后我以某种方式转换为三个数字的列表(hh,mm,sec.ms)
,然后转换为向量,假设下一步应该是使用 %*% c(3600,60,1)
进行向量乘法转换为数字秒。
这是我为每一行做的伪代码,以及每个时间字符串;完整代码位于底部:
for each row in dataframe { # vectorize this, loop_apply(), or whatever...
#for each time-column index i ('time1'..'time50') { # vectorize this...
hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i])
# Main computation
xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]) ))
# Minor task: fix up all the 'zero-time' events to be evenly spaced between -3..0
#}
}
因此涉及五个子问题:
strtime()
返回的列表进行矢量化处理?因为它返回了3个项目的列表,当传递2D数据帧或1D行时间字符串时,我们将获得3D或2D中间对象。 (我们在内部使用list-of-list?列表列表?列表数组?)parse_hhmmsecms()
?下面的代码段使用十个示例列 time41..50
(如果您想要更大的样本,请使用 random_hhmmsecms()
)
我尽力遵循these recommendations,这是可以重现的,因为我可以在六小时的工作中得到它:
# Each of 200,000 rows has 50 time strings (chr) like this...
xx <- structure(list(time41 = c("08:00:41.465", "08:00:50.573", "08:00:50.684"
), time42 = c("08:00:41.465", "08:00:50.573", "08:00:50.759"),
time43 = c("08:00:41.465", "08:00:50.573", "08:00:50.759"
), time44 = c("08:00:41.465", "08:00:50.664", "08:00:50.759"
), time45 = c("08:00:41.465", "08:00:50.684", "08:00:50.759"
), time46 = c("08:00:42.496", "08:00:50.684", "08:00:50.759"
), time47 = c("08:00:42.564", "08:00:50.759", "08:00:51.373"
), time48 = c("08:00:48.370", "08:00:50.759", "08:00:51.373"
), time49 = c("08:00:50.573", "08:00:50.759", "08:00:54.452"
), time50 = c("08:00:50.573", "08:00:50.759", "08:00:54.452"
)), .Names = c("time41", "time42", "time43", "time44", "time45",
"time46", "time47", "time48", "time49", "time50"), row.names = 3:5, class = "data.frame")
# Handle millisecond timing and time conversion
options('digits.secs'=3)
# Parse "HH:MM:SS.sss" timestring into (numeric) number of seconds (Very slow)
parse_hhmmsecms <- function(t) {
as.numeric(substr(t,1,2))*3600 + as.numeric(substr(t,4,5))*60 + as.numeric(substr(t,7,12)) # WORKS, V SLOW
#c(3600,60,1) %*% sapply((strsplit(t[1,]$time1, ':')), as.numeric) # SLOW, NOT VECTOR
#as.vector(as.numeric(unlist(strsplit(t,':',fixed=TRUE)))) %*% c(3600,60,1) # WANT TO VECTORIZE THIS
}
random_hhmmsecms <- function(n=1, min=8*3600, max=16*3600) {
# Generate n random hhmmsecms objects between min and max (8am:4pm)
xx <- runif(n,min,max)
ss <- xx %% 60
mm <- (xx %/% 60) %% 60
hh <- xx %/% 3600
sprintf("%02d:%02d:%05.3f", hh,mm,ss)
}
xx$logtime45 <- xx$logtime44 <- xx$logtime43 <- xx$logtime42 <- xx$logtime41 <- NA
xx$logtime50 <- xx$logtime49 <- xx$logtime48 <- xx$logtime47 <- xx$logtime46 <- NA
# (we pass index vectors as the dataframe column ordering may change)
Ctime <- which(colnames(xx)=='time41') : which(colnames(xx)=='time50')
Clogtime <- which(colnames(xx)=='logtime41') : which(colnames(xx)=='logtime50')
for (i in 40:nrow(xx)) {
#if (i%%100==0) { print(paste('... row',i)) }
hhmmsecms_50 <- parse_hhmmsecms(xx$time50[i])
xx[i,Clogtime] <- -10*log10(1000*(hhmmsecms_50 - parse_hhmmsecms(xx[i,Ctime]) ))
# Now fix up all the 'zero-time' events to be evenly spaced between -3..0
Czerotime.p <- which(xx[i,Clogtime]==Inf | xx[i,Clogtime]>-1e-9)
xx[i,Czerotime.p] <- seq(-3,0,length.out=length(Czerotime.p))
}
答案 0 :(得分:2)
你可能会过度复杂化。
从做毫秒的基类开始(在适当的操作系统上甚至是微秒),但请注意
您需要设置options("digits.secs"=7)
(这是可以显示的最大值)才能看到它们显示
您需要strptime
等
所有这些都在文档中,在SO上有无数的例子。
快速举例:
R> someTime <- ISOdatetime(2011, 12, 27, 2, 3, 4.567)
R> someTime
[1] "2011-12-27 02:03:04.567 CST"
R> now <- Sys.time()
R> now
[1] "2011-12-27 16:48:20.247298 CST" # microsecond display on Linux
R>
R> txt <- "2001-02-03 04:05:06.789123"
R> strptime(txt, "%Y-%m-%d %H:%M:%OS") # note the %0S for sub-seconds
[1] "2001-02-03 04:05:06.789123"
R>
strptime
或as.POSIXct
等关键函数都已进行了矢量化,您可以将整列放在其中。