Подтвердить что ты не робот

R: Как обрабатывать время без дат?

У меня есть данные, которые включают Date, а также Time enter и Time exit. Эти последние два содержат такие данные: 08:02, 12:02, 23:45 и т.д.

Я хотел бы манипулировать данными Time eXXX - например, вычитать Time enter из Time exit для определения продолжительности работы или построить распределение Time enter и Time exit, например. чтобы увидеть, если большинство записей до 10:00, или если большинство выходов после 17:00.

Все пакеты, на которые я смотрел, требуют, чтобы дата предшествовала времени, например. 01/02/2012 12:33.

Возможно ли это, или я просто добавляю идентичную дату в каждый раз ради расчетов? Это кажется немного грязным!

4b9b3361

Ответ 1

Используйте класс "times" из пакета chron:

library(chron)

Enter <- c("09:12", "17:01")
Enter <- times(paste0(Enter, ":00"))

Exit <-  c("10:15", "18:11")
Exit <- times(paste0(Exit, ":00"))

Exit - Enter # durations

sum(Enter < "10:00:00") # no entering before 10am
mean(Enter < "10:00:00") # fraction entering before 10am

sum(Exit >  "17:00:00") # no exiting after 5pm
mean(Exit >  "17:00:00") # fraction exiting after 5pm

table(cut(hours(Enter), breaks = c(0, 10, 17, 24))) # Counts for indicated hours   
 ## (0,10] (10,17] (17,24] 
 ##      1       1       0 

table(hours(Enter))  # Counts of entries each hour
## 9 17 
## 1  1

stem(hours(Enter), scale = 2)
## The decimal point is at the |

##   9 | 0
##  10 | 
##  11 | 
##  12 | 
##  13 | 
##  14 | 
##  15 | 
##  16 | 
##  17 | 0

Графика:

tab <- c(table(Enter), -table(Exit))  # Freq at each time.  Enter is pos; Exit is neg.
plot(times(names(tab)), tab, type = "h", xlab = "Time", ylab = "Freq")
abline(v = c(10, 17)/24, col = "red", lty = 2) # vertical red lines
abline(h = 0)  # X axis

screenshot

Ответ 2

Будет ли что-то подобное работать?

SubstracTimes <-  function(TimeEnter, TimeExit){
  (as.numeric(format(strptime(TimeExit, format ="%H:%M"), "%H")) + 
  as.numeric(format(strptime(TimeExit, format ="%H:%M"), "%M"))/60) -
  (as.numeric(format(strptime(TimeEnter, format ="%H:%M"), "%H")) + 
   as.numeric(format(strptime(TimeEnter, format ="%H:%M"), "%M"))/60)
}

Тестирование:

TimeEnter <- "08:02"
TimeExit <- "12:02"
SubstracTimes(TimeEnter, TimeExit)
> SubstracTimes(TimeEnter, TimeExit)
[1] 4

Ответ 3

Спасибо за отзыв и извините за путаницу, я немного отредактировал его, чтобы уточнить.

Новое редактирование:

Во- первых, chron пакет и strptime с фиксированным форматом и хорошо работать, как показано в других ответах. Я просто хочу немного представить lubridate, так как он более прост в использовании и гибок с форматом времени.

Пример данных

df <- data.frame(TimeEnterChar = c(rep("07:58", 10), "08:02", "08:03", "08:05", "08:10", "09:00"),
                 TimeExitChar  = c("16:30", "16:50", "17:00", rep("17:02", 10), "17:30", "18:59"),
                 stringsAsFactors = F)

Если все, что вам нужно, это подсчитать, сколько времени ввода было позже 8:00, тогда вы можете сравнить персонажа напрямую. Ниже бы 5 раз вход был позже.

sum(df$TimeEnterChar > "08:00")

Если вы хотите больше, лично мне нравится пакет lubridate при работе с данными о времени, особенно с отметками времени и датами, хотя это вообще не является темой этого поста.

library(lubridate)
# Convert character to a "Period" class by lubridate, shows in form of H M S
df$TimeEnterTime <- hm(df$TimeEnterChar)
df$TimeExitTime  <- hm(df$TimeExitChar)
head(df)

sum(df$TimeEnterTime > hm("08:00"))

Вы все еще можете сравнить время.

Еще немного об их использовании в качестве числа: я предполагаю, что требуется только минутное время. Таким образом, я разделил количество секунд на 60, чтобы получить количество минут.

df$DurationMinute <- as.numeric( df$TimeExitTime - df$TimeEnterTime )/60
hist(df$DurationMinute, breaks = seq(500, 600, 5))

head(df)
  TimeEnterChar TimeExitChar TimeEnterTime TimeExitTime DurationMinute
1         07:58        16:30     7H 58M 0S   16H 30M 0S            512
2         07:58        16:50     7H 58M 0S   16H 50M 0S            532
3         07:58        17:00     7H 58M 0S    17H 0M 0S            542
4         07:58        17:02     7H 58M 0S    17H 2M 0S            544
5         07:58        17:02     7H 58M 0S    17H 2M 0S            544
6         07:58        17:02     7H 58M 0S    17H 2M 0S            544

Вы можете просто построить гистограмму, чтобы увидеть распределение продолжительности времени между входом и выходом.

Вы также можете посмотреть на распределение времени входа/выхода. Но для преобразования оси требуются определенные усилия.

df$TimeEnterNumMin <- as.numeric(df$TimeEnterTime) / 60
df$TimeExitNumMin  <- as.numeric(df$TimeExitTime) / 60

hist(df$TimeEnterNumMin, breaks = seq(0, 1440, 60), xaxt = 'n', main = "Whole by 1hr")
axis(side = 1, at = seq(0, 1440, 60), labels = paste0(seq(0, 24, 1), ":00"))

hist(df$TimeEnterNumMin, breaks = seq(420, 600, 15), xaxt = 'n', main = "Morning by 15min")
axis(side = 1, at = seq(420, 600, 60), labels = paste0(seq(7, 10, 1), ":00"))

enter image description here

Я не полировал сюжет и не делал ось гибкой. Пожалуйста, делайте это исходя из ваших потребностей. Надеюсь, это поможет.


Ниже старый бесполезный пост: (читать не нужно. Хранится, чтобы комментарии не выглядели странно)

Наткнулся на похожую проблему и вдохновился этим постом. @Г. Гротендик и @David Arenburg предоставили отличные ответы для изменения времени.

Для сравнения, я чувствую, что время превращается в числовую помощь. Вместо сравнения "11:22:33" с "9:00:00", сравнивая as.numeric(hms("11:22:33")) (что составляет 40953 секунды) и as.numeric(hms("9:00:00")) (32400) было бы намного проще.

as.numeric(hms("11:22:33")) > as.numeric(hms("9:00:00"))  &  as.numeric(hms("11:22:33")) < as.numeric(hms("17:00:00"))
[1] TRUE

В приведенном выше примере показано 11:22:33 между 9 утра и 5 вечера.

Для извлечения только времени из объекта date или POSIXct сработает substr("2013-10-01 11:22:33 UTC", 12, 19), хотя выглядит глупо менять объект времени на строку/символ и обратно на снова

Преобразование времени в числовое значение должно работать для построения графика как @G. Гротендик отчаивался. Вы можете преобразовать числа обратно во времени, как необходимо для меток оси X.