R extrae componentes de tiempo de cadenas semi-estándar
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ónDefinitivamente, @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:
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}
}