У меня есть столбец продолжительности, хранящийся в виде строк в кадре данных. Я хочу преобразовать их в соответствующий объект времени, вероятно POSIXlt. Большинство строк легко разобрать с помощью этого метода:
> 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 определенно была правильная идея с динамическим созданием строки форматирования на основе проверки различных условий в формате даты. Добавление 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}
}