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

Настройка

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

Вопросы

  1. Что такое «Путь R» для обработки всех возможных форматов строк? Возможно, протестировать и извлечь каждый элемент по отдельности, а затем рекомбинировать?
  2. Является ли POSIXlt подходящим целевым классом? Мне нужна продолжительность без какого-либо конкретного времени начала, поэтому добавление ложных данных о годе и месяце ( 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}

}
7
задан Community 23 May 2017 в 12:15
поделиться