R 如何获得具有多个单位的输出时间差
你好 我在as.POSIXct中有两个日期列,格式为YYYY-MM-DD HH:MM:SS。我想得到两者之间的差异,以天小时:秒的格式显示。以下是一些虚拟数据:R 如何获得具有多个单位的输出时间差,r,time,posixct,difftime,R,Time,Posixct,Difftime,你好 我在as.POSIXct中有两个日期列,格式为YYYY-MM-DD HH:MM:SS。我想得到两者之间的差异,以天小时:秒的格式显示。以下是一些虚拟数据: a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST", "2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 A
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST",
"2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST")
b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST",
"2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST")
ab<-data.frame(a,b)
我想得到a和b之间的差值,或者从时间b中减去时间a,得到X天X小时X秒的输出
我在下面使用了difftime,以及不同设置的单位:
ab$time_difference<-difftime(ab$b, ab$a)
ab
a b time_difference
2018-03-20 11:52:25 AST 2018-04-09 18:39:38 AST 486.786944 hours
2018-03-20 12:51:25 AST 2018-06-23 19:13:14 AST 2286.363611 hours
2018-03-20 14:19:04 AST 2018-03-20 23:23:03 AST 9.066389 hours
2018-03-21 14:12:12 AST 2018-05-10 21:29:28 AST 1207.287778 hours
2018-03-21 12:09:22 AST 2018-03-22 03:17:23 AST 15.133611 hours
2018-03-21 15:28:01 AST 2018-05-12 00:19:39 AST 1232.860556 hours
ab$time\u differencehms库可以在这里提供一些帮助:
library(hms)
as.hms(ab$time_difference, format="%H:%M:S")
# 486:47:13
# 2286:21:49
# 09:03:59
# 1207:17:16
# 15:08:01
# 1232:51:38
有关其他选项,请参见此问题:
以下是上述问题答案中的代码:
Fmt <- function(x) UseMethod("Fmt")
Fmt.difftime <- function(x) {
units(x) <- "secs"
x <- unclass(x)
NextMethod()
}
Fmt.default <- function(x) {
y <- abs(x)
sprintf("%s%02d:%02d:%02d:%02d",
ifelse(x < 0, "-", ""), # sign
y %/% 86400, # days
y %% 86400 %/% 3600, # hours
y %% 3600 %/% 60, # minutes
y %% 60 %/% 1) # seconds
}
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST",
"2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST")
b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST",
"2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST")
ab<-data.frame(a,b)
#Passing two dates to the function(s)
Fmt(as.POSIXct(ab$b)-as.POSIXct(ab$a))
#Passing a time difference in seconds
Fmt(difftime(ab$b, ab$a, units="secs"))
Fmtrequire(润滑)
a由于您需要天、小时、分钟、秒,我们可以使用lubridate
软件包获得此结果:
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST",
"2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST")
b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST",
"2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST")
a = as.POSIXct(a)
b = as.POSIXct(b)
library(lubridate)
timespan = interval(ymd_hms(ab[,1]), ymd_hms(ab[,2]))
> as.period(timespan)
[1] "20d 6H 47M 13S" "3m 3d 6H 21M 49S" "9H 3M 59S" "1m 19d 7H 17M 16S"
[5] "15H 8M 1S" "1m 20d 8H 51M 38S"
使用sprintf
和模块化算法:
# first, be sure to specify units in difftime, or it will internally
# choose units for each row
# using 'secs' here since it's the lowest common denominator
# wrapping as.double() to remove the class attribute which will
# screw up dispatch to Ops below
ab$time_difference <- as.double(difftime(ab$b, ab$a, units = 'secs'))
# 3600 = 60*60 seconds in an hour;
# 86400 = 3600*24 seconds in a day
ab$hms = with(ab, sprintf('%d days; %d hours; %d seconds',
time_difference %/% 86400L,
(time_difference %% 86400L) %/% 3600L,
time_difference %% 3600L))
ab$hms
# [1] "20 days; 6 hours; 2833 seconds" "95 days; 6 hours; 1309 seconds"
# [3] "0 days; 9 hours; 239 seconds" "50 days; 7 hours; 1036 seconds"
# [5] "0 days; 15 hours; 481 seconds" "51 days; 8 hours; 3098 seconds"
#首先,确保在difftime中指定单位,否则将在内部指定
#为每行选择单位
#在这里使用“secs”,因为它是最小的公分母
#将包装为.double()以删除将
#把调度工作搞砸了
ab$time_difference同一天的时差如何等于-785104d-7H-7m0s
?为此使用时段对象似乎不是一个理想的想法-“因为时段没有固定的长度”,谢谢。输出中的第二个值为3m和21m。。。小写的m代表毫秒吗?如果是的话,有没有办法去掉毫秒?小写的“m”代表月(因为日期之间的差异很大)。啊,我明白了,谢谢。由于月份的天数不同,有没有办法让月份默认为天?所以我的输出将是天、小时、分钟、秒?@ElizabethSmith:是的,我们可以通过指定格式将月改为天。我已经编辑了我的答案,并在最后添加了一些代码来完成这项工作。谢谢,这是通过将时差列重新格式化为小时:分钟:秒来实现的,但我无法将其格式化为天。我还研究了您链接的问题,并尝试使用该函数,但不太了解如何使用该函数,无法使其重新格式化我的数据列。感谢您的回复和编辑@Dave2e。我已经运行了代码,但不断收到错误消息“error in*tmp*
$diff:$operator对原子向量无效”。我尝试了is.atomic,每一列都实现了。根据这个问题,我必须使用Fmt(as.POSIXct(ab[“b”])-as.POSIXct(ab[“a”]),但是当我使用str(ab)时,我会得到错误“不知道如何将'tag_final[“last_pos”]”转换为类“POSIXct”它说这些列在POSIXct中。我这里缺少什么?如果这些列是类POSIXct,那么它们都准备好了一个日期时间对象,您应该使用difftime
函数。如果您引用列名,则需要使用双括号Fmt(as.POSIXct(ab[“b”]])-as.POSIXct(ab[“a”]])
require(lubridate)
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST",
"2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST")
b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST",
"2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST")
# Make df
ab <- data.frame(a = as.POSIXct(a),b = as.POSIXct(b),stringsAsFactors = FALSE)
# Time diff
ab$time_difference <- ab$b - ab$a
ab$time_difference <- as.duration(ab$time_difference)
ab$time_difference
1 2018-03-20 11:52:25 2018-04-09 18:39:38 1752433s (~2.9 weeks)
2 2018-03-20 12:51:25 2018-06-23 19:13:14 8230909s (~13.61 weeks)
3 2018-03-20 14:19:04 2018-03-20 23:23:03 32639s (~9.07 hours)
4 2018-03-21 14:12:12 2018-05-10 21:29:28 4346236s (~7.19 weeks)
5 2018-03-21 12:09:22 2018-03-22 03:17:23 54481s (~15.13 hours)
6 2018-03-21 15:28:01 2018-05-12 00:19:39 4438298s (~7.34 weeks)
a<-c("2018-03-20 11:52:25 AST", "2018-03-20 12:51:25 AST", "2018-03-20 14:19:04 AST",
"2018-03-21 14:12:12 AST", "2018-03-21 12:09:22 AST", "2018-03-21 15:28:01 AST")
b<-c("2018-04-09 18:39:38 AST", "2018-06-23 19:13:14 AST", "2018-03-20 23:23:03 AST",
"2018-05-10 21:29:28 AST", "2018-03-22 03:17:23 AST", "2018-05-12 00:19:39 AST")
a = as.POSIXct(a)
b = as.POSIXct(b)
library(lubridate)
timespan = interval(ymd_hms(ab[,1]), ymd_hms(ab[,2]))
> as.period(timespan)
[1] "20d 6H 47M 13S" "3m 3d 6H 21M 49S" "9H 3M 59S" "1m 19d 7H 17M 16S"
[5] "15H 8M 1S" "1m 20d 8H 51M 38S"
> as.period(timespan, unit = "day")
[1] "20d 6H 47M 13S" "95d 6H 21M 49S" "9H 3M 59S" "50d 7H 17M 16S"
[5] "15H 8M 1S" "51d 8H 51M 38S"
# first, be sure to specify units in difftime, or it will internally
# choose units for each row
# using 'secs' here since it's the lowest common denominator
# wrapping as.double() to remove the class attribute which will
# screw up dispatch to Ops below
ab$time_difference <- as.double(difftime(ab$b, ab$a, units = 'secs'))
# 3600 = 60*60 seconds in an hour;
# 86400 = 3600*24 seconds in a day
ab$hms = with(ab, sprintf('%d days; %d hours; %d seconds',
time_difference %/% 86400L,
(time_difference %% 86400L) %/% 3600L,
time_difference %% 3600L))
ab$hms
# [1] "20 days; 6 hours; 2833 seconds" "95 days; 6 hours; 1309 seconds"
# [3] "0 days; 9 hours; 239 seconds" "50 days; 7 hours; 1036 seconds"
# [5] "0 days; 15 hours; 481 seconds" "51 days; 8 hours; 3098 seconds"