Лучшее на сегодняшний день решение: base-R + data.table + fasttime
#!/usr/bin/env Rscript
# above this point: set d_f and o_f to valid file paths
totTime<-proc.time()
install.load <- function(package.name)
{
if (!require(package.name, character.only=T)) install.packages(package.name)
library(package.name, character.only=T)
}
pp<-function(...) {
print(paste0(...))
}
ISO2Human<-function(x) {
ot<-substr(x,1,19) # ignore fractional seconds and "Z"
substr(ot,11,12)<-" "
if(anyNA(ot)) ot<-substr(x,1,10)
return(ot)
}
install.load('data.table')
install.load('fasttime')
pp("parameters read and libraries loaded: ",timetaken(totTime))
main <- function() {
dat<-fread(d_f,fill=TRUE)
# notably dat has a "d_utc" column in YYYY-MM-DD hh:nn:ss format
pp("data file Read: ",timetaken(totTime)) # 5.200sec
# A fair amount of code is inserted here. Highlights include
# 1. As computations appear to be faster in double/numeric form
# than POSIXct (and starts as character), I adjust it as follows:
# dat[,d_utc:=setattr(fastPOSIXct(d_utc,tz="GMT"),"class","numeric")]
# 2. dat gets merged with another DT using foverlaps, producing fo (see https://stackoverflow.com/q/53858287/4228193)
# as we resume code, 8.690sec have elapsed
# As my target timezone is UTC-08:00 (POSIXct ETC/GMT+8), I subtract 28800 seconds.
# But to protect against a rounding error in the double type
# (and because I have some fractional second data that I want to round)
# I add 0.5 to this value.
fo[,d_pst:=setattr(d_utc-28799.5,c("POSIXct","POSIXt"))][,d_utc:=NULL]
pp("timestamps adjusted to PST (UTC-08:00): ",timetaken(totTime)) # 16.8sec
Это особая часть кода, которую я пытался оптимизировать в этом вопросе;но при этом я обнаружил, что некоторые из приведенных выше преобразований типов кажутся более оптимальными.
tf<-tempfile()
fwrite(fo,file=tf)
fo<-fread(tf)
# fread reads in as character, not timestamps
# POSIXct's as.character and format calls are much slower than fwrite + fread (!!!)
fo[,DetectDate:=ISO2Human(DetectDate)]
# this truncates seconds, effectively rounding due to the previous adjustment of 0.5s
unlink(tf) # delete file
pp("coerced to string: ",timetaken(totTime)) # 26.9sec
fwrite(fo, file = o_f, quote = FALSE)
pp("output file written: ",timetaken(totTime)) # 27.1sec
# aren't SSDs awesome?
}
main()
Другие решения
Блок на основе Lubridate (без временного файла),Временами вверху являются мм: сс
# 01:17
j<-copy(fo)
tt<-proc.time()
j[,c("dd","dt"):=IDateTime(d_pst, ms="nearest")]
# if adding 0.5 seconds, trunc rather than nearest
j[,d_pst:=paste(dd,dt)][,c("dd","dt"):=NULL]
timetaken(tt) # 1:17
j
j[,lapply(.SD,class)]
rm(j)
преобразование POSIXct в base-R в строку с использованием as.character или в формате
# 01:02
j<-copy(fo)
tt<-proc.time()
j[,DD2:=format(DetectDate,"%Y-%m-%d %H:%M:%S")]
timetaken(tt) # 1:02
j
j[,lapply(.SD,class)]
rm(j)
неявное преобразование в base-R в символ + дата сплайсинга иtime
# 12:36
j<-copy(fo)
tt<-proc.time()
j[,DD2:=paste(lapply(DetectDate,substr,1,10),lapply(DetectDate,substr,12,19))]
timetaken(tt) # 12:36
j
j[,lapply(.SD,class)]
rm(j)
base-R, избегая лапы (глупый я)
# 02:29
j<-copy(fo)
tt<-proc.time()
j[,DD2:=paste(substr(DetectDate,1,10),substr(DetectDate,12,19))]
timetaken(tt) # 2:29
j
j[,lapply(.SD,class)] # just to confirm our target column is character
rm(j)
data.table + base-R, но используя tstrsplit и вставку data.table вместо того, чтобы захватыватьдиапазон символов
# 00:24
j<-copy(fo)
tt<-proc.time()
tf<-tempfile()
fwrite(j,file=tf)
fo2<-fread(tf)
fo2[,c("compDate","compTime","compMS"):=tstrsplit(DetectDate,"[TZ.]")][
,DD2:=paste(compDate,compTime)]
unlink(tf)
timetaken(tt) # 0:24
fo2
fo2[,lapply(.SD,class)]
rm(j,tf,fo2)
в основном оптимальное решение, хотя повторное использование имен переменных и полей сокращает это до 10 с
# 00:14
fap<-function(x) {
ot<-substr(x,1,19)
substr(ot,11,12)<-" "
if(is.na(ot)) ot<-substr(x,1,10)
return(ot)
}
j<-copy(fo)
tt<-proc.time()
tf<-tempfile()
fwrite(j,file=tf)
fo2<-fread(tf)
fo2[,DD2:=fap(DetectDate)]
unlink(tf)
timetaken(tt) # 0:14
fo2
fo2[,lapply(.SD,class)]
rm(j,tf,fo2,fap)
Я использую (n) SSD,что, вероятно, значительно ускоряет решение временного файла по сравнению со «стандартной» настройкой