R中非唯一行之间的日期时间差异

时间:2016-05-23 00:12:50

标签: r datetime

我在SO找到了答案,但这对我不起作用。我想要的是如下:

c_id    c_time
1    2012-08-15 00:00:30
1    2012-08-15 00:01:21
1    2012-08-15 00:01:25
2    2012-08-15 00:02:40
2    2012-08-15 00:03:41

我想在小时,分钟或秒中获得c_id变量的第一次和最后一次出现之间的时间差。

c_diff
00:00:55 
00:01:01

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:4)

这是一个简单的问题,即通过不同的c_id对时间进行分组并获取最大值和最小值之间的差值。 有几种方法可以做到这一点,我更喜欢使用d_dlyr包的group_by函数。

#sample data    
#dput(df)
    df<-df<-structure(list(c_id = c(1, 1, 1, 2, 2), c_time = structure(c(1344988830, 
        1344988881, 1344988885, 1344988960, 1344989021), class = c("POSIXct", 
    "POSIXt"), tzone = "GMT")), .Names = c("c_id", "c_time"), row.names = c(NA, 
       -5L), class = "data.frame")


library(dplyr)
out<-summarize(group_by(df, c_id), delta=difftime(max(c_time), min(c_time), units = "mins"))

要将列增量转换为所需格式,您需要使用chron包:

library(chron)
zero <- structure(0, units = "secs", class = "difftime")
dd.day <- as.vector((out$delta + zero)/(24*60*60))
out$delta<-times(dd.day) 

out
# Source: local data frame [2 x 2]
# 
#    c_id    delta
#   (dbl)   (tims)
# 1     1 00:00:55
# 2     2 00:01:01

应该有一种更简单的方法,但我在2005年的一篇文章中找到答案(http://grokbase.com/t/r/r-help/055n2qa21v/r-print-format-for-difftime

答案 1 :(得分:3)

tapply可能有帮助。

>c_id <- c(1,1,1,2,2)
>c_time <- as.POSIXct(c("2012-08-15 00:00:30","2012-08-15 00:01:21","2012-08-15 00:01:25","2012-08-15 00:02:40","2012-08-15 00:03:41"))
>c_diff <- tapply(c_time, c_id, function(x) max(as.numeric(x))-min(as.numeric(x)))
>c_diff
 1  2 
55 61 

答案 2 :(得分:2)

获得差异很简单:只需减去,即max(df$c_time) - min(df$c_time)。但是,在将其应用于多个子集时,您可能会发现单位变得不稳定,因此明确使用difftime以便设置单位是一个好主意。在aggregate

aggregate(c_time ~ c_id, df, function(x){difftime(max(x), min(x), units ='secs')})
#  c_id c_time
# 1    1    55 
# 2    2    61 

但是,这不是您想要的时间格式。 chron有一个很好的时间类,假设你不只是想使用字符串。它减去了比difftime

更好的结果
aggregate(c_time ~ c_id, df, function(x){x <- chron::as.chron(x); max(x) - min(x)})
#   c_id   c_time
# 1    1 00:00:55
# 2    2 00:01:01

# or in dplyr
library(dplyr)

df %>% mutate(c_time = chron::as.chron(c_time)) %>% 
    group_by(c_id) %>% 
    summarise(range = max(c_time) - min(c_time))
# Source: local data frame [2 x 2]
# 
#    c_id    range
#   (int)   (tims)
# 1     1 00:00:55
# 2     2 00:01:01

# or data.table
library(data.table)

setDT(df)[, .(c_id, c_time = chron::as.chron(c_time))
          ][, .(range = max(c_time) - min(c_time)), by = c_id]
#    c_id    range
# 1:    1 00:00:55
# 2:    2 00:01:01

或者使用data.table的ITime而不是chron::times,尽管它在减去时会返回秒数:

setDT(df)[, .(c_id, c_time = as.ITime(c_time))
          ][, .(range = as.ITime(as.POSIXct(max(c_time) - min(c_time), 
                                            'UTC', origin))), by = c_id]
#    c_id    range
# 1:    1 00:00:55
# 2:    2 00:01:01

如果你确实想要字符串而不是格式化时间,你实际上可以将它保存在所有基数R中:

aggregate(c_time ~ c_id, df, 
          function(x){format(as.POSIXct(as.numeric(difftime(max(x), 
                                                            min(x), 
                                                            units ='secs')), 
                                        'UTC', origin = origin), 
                             '%T')})
#   c_id   c_time
# 1    1 00:00:55
# 2    2 00:01:01