0

我正在尝试制作一个将时间(以字符形式)转换为十进制格式的函数,以便 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但我不知道为什么它没有被矢量化的原因。

我也会有兴趣获得更好的功能来做我想做的事情。我看到解释了我的问题的一部分,但没有提供线索来做我正在尝试的事情。

4

4 回答 4

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
于 2014-04-19T20:55:17.907 回答
2
 as.numeric( strptime(times, "%H:%M:%S")-strptime(Sys.Date(), "%Y-%m-%d" ))
[1] 12.386667 10.395833  9.136111

与 Roland 的基本相同,但绕过了一些步骤,我尽量避免使用difftime。出现了太多错误,因为我并不真正了解函数或类......或其他东西。当我与罗兰的时间相比时,他的时间更快。那好吧。

模仿@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
于 2014-04-19T21:21:28.110 回答
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)strapply在 gsubfn 包中解析字符串稍微容易一些:

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

ADDED添加了更多解决方案。

于 2014-04-19T21:34:22.557 回答
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))
})
于 2014-04-19T20:54:03.957 回答