R извлекает компоненты времени из полустандартных строк

Setup

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

Проблема в том, чтоthe string drops zero-valued elements, Таким образом желаемое значение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
Questions What is the "R Way" to handle all the possible string formats? Perhaps test for and extract each element individually, then recombine? Is POSIXlt the right target class? I need duration free from any specific start time, so the addition of false year and month data (2012-01-) is troubling. Solution

У @mplourde определенно была правильная идея с динамическим созданием строки форматирования, основанной на тестировании различных условий в формате даты. Добавлениеcut(Sys.Date(), breaks='years') в качестве базовой линии дляdatediff было также хорошо, но не смог объяснить критическую причуду вas.POSIXct() Note: I'm using R2.11 base, this may have been fixed in later versions.

Выход из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 функция должна быть:

The start of the first day of the current year if the input string has a day component The start of the current day if the input string does not have a day component

Это может быть достигнуто путем изменения параметра устройства на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}

}

Ответы на вопрос(2)

Ваш ответ на вопрос