R extrae componentes de tiempo de cadenas semi-estándar

Preparar

Tengo una columna de duraciones almacenadas como cadenas en un marco de datos. Quiero convertirlos en un objeto de tiempo apropiado, probablementePOSIXlt. La mayoría de las cadenas son fáciles de analizar utilizandoeste método:

> 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

Las duraciones faltantes están codificadas."--" y necesita ser convertido aNA - Esto ya sucede pero debe ser preservado.

El reto es queLa cadena deja caer los elementos de valor cero.. Así el valor deseado.2012-01-01 02:00:14 seria la cuerda"1 d 2 h 14 s". Sin embargo, esta cadena se analiza aNA con el simple analizador:

> 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
Preguntas¿Cuál es el "R Way" para manejar todos los formatos de cadena posibles? Tal vez pruebe y extraiga cada elemento individualmente, luego vuelva a combinar.¿Es POSIXlt la clase objetivo correcta? Necesito una duración libre de cualquier hora de inicio específica, por lo que la adición de datos falsos de año y mes (2012-01-) es preocupante.Solución

Definitivamente, @mplourde tuvo la idea correcta con la creación dinámica de una cadena de formato basada en la prueba de varias condiciones en el formato de fecha. La suma decut(Sys.Date(), breaks='years') como la línea de base para eldatediff También fue bueno, pero no tuvo en cuenta una peculiaridad crítica enas.POSIXct() Nota: estoy usando la base R2.11, esto puede haber sido arreglado en versiones posteriores.

La salida deas.POSIXct() Cambios dramáticos dependiendo de si se incluye o no un componente de fecha:

> 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"

Así, el segundo argumento para ladifftime la función debe ser:

El inicio del primer día del año en curso si la cadena de entradatiene un componente de díaEl inicio de lacorriente día si la cadena de entradano tener un componente de día

Esto se puede lograr cambiando el parámetro de la unidad en lacut función:

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}

}

Respuestas a la pregunta(2)

Su respuesta a la pregunta