我正在尝试创建一个将时间(字符形式)转换为十进制格式的函数,使得1对应于上午1点,23对应于11点,24表示当天结束。
这是执行此操作的两个功能。这里有一个函数矢量化,而其他函数
time2dec <- function(time0)
{
time.dec <-as.numeric(substr(time0,1,2))+as.numeric(substr(time0,4,5))/60+(as.numeric(substr(time0,7,8)))/3600
return(time.dec)
}
time2dec1 <- function(time0)
{
time.dec <-as.numeric(strsplit(time0,':')[[1]][1])+as.numeric(strsplit(time0,':')[[1]][2])/60+as.numeric(strsplit(time0,':')[[1]][3])/3600
return(time.dec)
}
这就是我得到的......
times <- c('12:23:12','10:23:45','9:08:10')
#>time2dec(times)
[1] 12.38667 10.39583 NA
Warning messages:
1: In time2dec(times) : NAs introduced by coercion
2: In time2dec(times) : NAs introduced by coercion
#>time2dec1(times)
[1] 12.38667
我知道time2dec
是向量化的,为最后一个元素提供NA,因为它以小时为单位提取9:
而不是9
。这就是我创建time2dec1
的原因,但我不知道为什么它没有被矢量化。
我也有兴趣获得更好的功能来做我想做的事情。 我看到this解释了我问题的一部分,但没有提供做我正在尝试的事情的线索。
答案 0 :(得分:4)
不要试图重新发明轮子:
times1 <- difftime(as.POSIXct(times, "%H:%M:%S", tz="GMT"),
as.POSIXct("0:0:0", "%H:%M:%S", tz="GMT"),
units="hours")
#Time differences in hours
#[1] 12.386667 10.395833 9.136111
as.numeric(times1)
#[1] 12.386667 10.395833 9.136111
答案 1 :(得分:2)
as.numeric( strptime(times, "%H:%M:%S")-strptime(Sys.Date(), "%Y-%m-%d" ))
[1] 12.386667 10.395833 9.136111
基本上与Roland相同,但绕过了一些步骤,如果可以,我尽量避免使用difftime
。有太多的错误出现,因为我真的不了解功能或类......或者其他什么。当我与Roland的时间相比时,他的速度更快了。哦,好吧。
模仿@ G.Grothendieck的努力(基本上与他优雅的背景解决方案类似:
num <- apply( matrix(scan(text=gsub(":", " ", ch), what=numeric(0)),nrow=3), 2,
function(x) x[1]+x[2]/60 +x[3]/3600 )
#Read 9 items
num
#[1] 12.386667 10.395833 9.136111
这实际上回答了原来的问题:
num <- sapply( strsplit(ch, ":"), function(x){ x2 <- as.numeric(x);
x2[1]+x2[2]/60 +x2[3]/3600})
num
#[1] 12.386667 10.395833 9.136111
答案 2 :(得分:2)
在下文中,我们将使用此测试向量:
ch <- c('12:23:12','10:23:45','9:08:10')
1)要修复问题中的解决方案,我们前缀为0,然后用最后两位替换任意3位数的字符串:
num.substr <- function(...) as.numeric(substr(...))
time2dec <- function(time0) {
t0 <- sub("\\d(\\d\\d)", "\\1", paste0(0, time0))
num.substr(t0, 1, 2) + num.substr(t0, 4, 5) / 60 + num.substr(t0, 7, 8) / 3600
}
time2dec(ch)
## [1] 12.386667 10.395833 9.136111
2)使用gsubfn包中的strapply
解析字符串会更容易:
strapply(ch, "^(.?.):(..):(..)",
~ as.numeric(h) + as.numeric(m)/60 + as.numeric(s)/36000,
simplify = c)
## [1] 12.383667 10.384583 9.133611
3)我们可以将字符串操作减少为仅删除冒号,然后将生成的字符串转换为数字,以便我们可以用数字方式对其进行操作:
num <- as.numeric(gsub(":", "", ch))
num %/% 10000 + num %% 10000 %/% 100 / 60 + num %% 100 / 3600
## [1] 12.386667 10.395833 9.136111
4) chron包中有一个"times"
类,内部表示一天中的几分之一。将其转换为小时可以提供简单的解决方案:
library(chron)
24 * as.numeric(times(ch))
## [1] 12.386667 10.395833 9.136111
已添加添加了更多解决方案。
答案 3 :(得分:1)
以下是您想要的
sapply(strsplit(times, ":"), function(d) {
sum(as.numeric(d)*c(1,1/60,1/3600))
})
一步一步:
strsplit(times, ":")
返回带有字符向量的列表。每个字符向量包含时间的三个部分(小时,分钟,秒)。我们现在想要将列表中的每个元素转换为数值。为此,我们需要对每个元素应用一个函数,并将后面的结果放入一个sapply
所做的向量中。
sapply(strsplit(times, ":", function(d) {
})
至于功能。我们首先需要使用as.numeric
将字符值转换为数值。我们将第一个元素与1相乘,第二个元素与1/60相乘,第三个元素与1/3600相乘并添加结果(我们使用sum
)。导致
sapply(strsplit(times, ":"), function(d) {
sum(as.numeric(d)*c(1,1/60,1/3600))
})