提问人:gisol 提问时间:3/26/2014 最后编辑:Gregor Thomasgisol 更新时间:12/11/2021 访问量:15646
R:如何处理没有日期的时间?
R: How to handle times without dates?
问:
我有数据,其中包括 以及 和 .后两者包含如下数据:、 等。Date
Time enter
Time exit
08:02
12:02
23:45
我想操作数据 - 例如,减去以计算持续时间,或绘制 和 的分布,例如查看大多数条目是否在 10:00 之前,或者大多数退出是否在 17:00 之后。Time eXXX
Time enter
Time exit
Time enter
Time exit
我看过的所有软件包都需要在时间之前有一个日期,例如 .01/02/2012 12:33
这是否可能,或者我应该为了计算而简单地在每次上附加一个相同的日期?这似乎有点乱!
答:
这样的事情会起作用吗?
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
评论
使用 chron 包中的类:"times"
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
感谢您的反馈,很抱歉造成混乱,我对其进行了一些编辑以澄清。
新编辑:
首先,包和固定格式都很好用,正如其他答案所证明的那样。我只想介绍一点,因为它更易于使用,并且时间格式灵活。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"))
我没有打磨剧情,也没有让轴线灵活。请根据您的需要进行操作。希望它有所帮助。
下面是旧的无用帖子:(无需阅读。 保留,以便评论看起来不奇怪)
遇到了类似的问题,并受到这篇文章的启发。 @G. Grothendieck 和 @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 点之间。
仅从日期或 POSIXct 对象中提取时间应该有效,尽管将时间对象更改为字符串/字符并再次变回时间看起来很愚蠢。substr("2013-10-01 11:22:33 UTC", 12, 19)
将时间转换为数字应该适用于格罗滕迪克@G所描述的绘图。您可以根据需要将数字转换回 x 轴标签的时间。
评论
hms("11:22:33") > hms("9:00:00") & hms("11:22:33") < hms("17:00:00")
as.numeric
hour(hms("11:22:33"))
评论