我有一列持续时间存储为数据帧中的字符串。我想将它们转换为适当的时间对象,可能是POSIXlt。大多数字符串都很容易使用this method解析:
> data <- data.frame(time.string = c(
+ "1 d 2 h 3 m 4 s",
+ "10 d 20 h 30 m 40 s",
+ "--"))
> data$time.span <- strptime(data$time.string, "%j d %H h %M m %S s")
> data$time.span
[1] "2012-01-01 02:03:04" "2012-01-10 20:30:40" NA
缺少的持续时间编码为"--"
,需要转换为NA
- 这已经发生但应该保留。
挑战在于字符串会丢弃零值元素。因此,期望值2012-01-01 02:00:14
将是字符串"1 d 2 h 14 s"
。但是,此字符串使用简单的解析器解析为NA
:
> data2 <- data.frame(time.string = c(
+ "1 d 2 h 14 s",
+ "10 d 20 h 30 m 40 s",
+ "--"))
> data2$time.span <- strptime(data2$time.string, "%j d %H h %M m %S s")
> data2$time.span
[1] NA "2012-01-10 20:30:40" NA
2012-01-
)是令人不安的。 @mplourde肯定有正确的想法w /动态创建格式化字符串基于测试日期格式中的各种条件。添加cut(Sys.Date(), breaks='years')
作为datediff
的基线也很好,但未能解释as.POSIXct()
中的一个关键怪癖注意:我使用的是R2.11基础,这可能已在以后的版本中修复。
as.POSIXct()
的输出会根据是否包含日期组件而发生显着变化:
> x <- "1 d 1 h 14 m 1 s"
> y <- "1 h 14 m 1 s" # Same string, no date component
> format (x) # as specified below
[1] "%j d %H h %M m %S s"
> format (y)
[1] "% H h % M %S s"
> as.POSIXct(x,format=format) # Including the date baselines at year start
[1] "2012-01-01 01:14:01 EST"
> as.POSIXct(y,format=format) # Excluding the date baselines at today start
[1] "2012-06-26 01:14:01 EDT"
因此difftime
函数的第二个参数应为:
这可以通过更改cut
功能的单位参数来完成:
parse.time <- function (x) {
x <- as.character (x)
break.unit <- ifelse(grepl("d",x),"years","days") # chooses cut() unit
format <- paste(c(if (grepl("d", x)) "%j d",
if (grepl("h", x)) "%H h",
if (grepl("m", x)) "%M m",
if (grepl("s", x)) "%S s"), collapse=" ")
if (nchar(format) > 0) {
difftime(as.POSIXct(x, format=format),
cut(Sys.Date(), breaks=break.unit),
units="hours")
} else {NA}
}
答案 0 :(得分:11)
difftime
个对象是可以添加到POSIXct
或POSIXlt
个对象的持续时间对象。也许你想用这个而不是POSIXlt
?
关于从字符串到时间对象的转换,您可以执行以下操作:
data <- data.frame(time.string = c(
"1 d 1 h",
"30 m 10 s",
"1 d 2 h 3 m 4 s",
"2 h 3 m 4 s",
"10 d 20 h 30 m 40 s",
"--"))
f <- function(x) {
x <- as.character(x)
format <- paste(c(if (grepl('d', x)) '%j d',
if (grepl('h', x)) '%H h',
if (grepl('m', x)) '%M m',
if (grepl('s', x)) '%S s'), collapse=' ')
if (nchar(format) > 0) {
if (grepl('%j d', format)) {
# '%j 1' is day 0. We add a day so that x = '1 d' means 24hrs.
difftime(as.POSIXct(x, format=format) + as.difftime(1, units='days'),
cut(Sys.Date(), breaks='years'),
units='hours')
} else {
as.difftime(x, format, units='hours')
}
} else { NA }
}
data$time.span <- sapply(data$time.string, FUN=f)
答案 1 :(得分:3)
我认为lubridate会有更好的运气:
来自Dates and Times Made Easy with lubridate:
5.3。持续时间
...
持续时间的长度对于闰年,闰秒和夏令时来说是不变的 因为持续时间是以秒为单位。因此,持续时间具有一致的长度和 可以很容易地与其他持续时间进行比较。持续时间是适当的对象 比较基于时间的属性,例如速度,速率和生命周期。 lubridate使用基数R的difftime类作为持续时间。额外的difftime方法 已经创建,以促进这一点。
lubridate使用基数R的difftime类作为持续时间。额外的difftime方法 已经创建,以促进这一点。
...
使用辅助函数dyears(),dweeks(),ddays(),dhours(),dminutes()和dseconds()可以轻松创建Duration对象。标题中的d代表持续时间,并将这些对象与周期对象区分开来,这将在5.4节中讨论。每个对象使用上面给出的估计关系以秒为单位创建持续时间。
尽管如此,我还没有找到一个将字符串解析为持续时间的函数。
您还可以查看Ruby's Chronic,了解解析的优雅时间。我没有为R找到这样的库。