基于时差的R分组

时间:2017-05-10 18:13:41

标签: r group-by

这是我的数据框:

df <- data.frame(col_1 = c('11/13/2007', '11/17/2007', '11/19/2007', '11/25/2007', '11/28/2007'),
                 col_2 = c('A', 'B', 'C', 'D', 'E'))

我想添加列,它会使用col_1中日期的时差来对元素进行分组。例如,第一行,第二行和第三行将在第1组中,因为日期差异仅少于5天(在每个连续日期之间),第四行和第五行将在第2组中。我们将从连续两个日期获得两个组2007年11月19日'和'11 / 25/2007'的差异超过5天。

我可以计算日期之间的日差异,但现在确定如何创建分组。我更喜欢dplyr的解决方案,但是任何建议都值得赞赏。

3 个答案:

答案 0 :(得分:3)

我认为你可以创建这些群体而不必做任何特别花哨的事情。

首先我们清理col_1然后获取组。注意我创建了lag_time_diff来帮助提高可读性,但如果需要,您可以选择将其直接放在cumsum中。

df$col_1 <- as.POSIXct(df$col_1, format = "%m/%d/%Y")

lag_time_diff <- difftime(df$col_1, lag(df$col_1, default = df$col_1[1]), units = "days")
df$group <- cumsum(ifelse(lag_time_diff>5,1,0))


df
#       col_1 col_2 group
#1 2007-11-13     A     0
#2 2007-11-17     B     0
#3 2007-11-19     C     0
#4 2007-11-25     D     1
#5 2007-11-28     E     1

所有这一切都是检查滞后的时间差是否> 5,如果它是1的索引,否则保持相同的值。

答案 1 :(得分:1)

这种方法创建了一个带有一些冗余信息的最终产品,所以肯定有一种更有效的方法,但这似乎可以解决你的困境:

## generate data
df <- data.frame(col_1 = c('11/13/2007', 
                           '11/17/2007', 
                           '11/19/2007', 
                           '11/25/2007', 
                           '11/28/2007'),
                 col_2 = c('A', 'B', 'C', 'D', 'E'))

## convert date to date class
df$col_1 <- as.Date(as.character(df$col_1), format = "%m/%d/%Y")

## define function for difftime variable
foo <- function(d1, d) sapply(d, function(x) difftime(d1, x))

## apply function to each observation and convert to data frame
dfdat <- structure(
    data.frame(sapply(df$col_1, foo, df$col_1)),
    names = as.character(df$col_1))

## combine with original data
df <- cbind(df, dfdat)

## use tidyr package to make long form
df <- tidyr::gather(df, referent, difftime, -col_1, -col_2)

## load dplyr 
library(dplyr)

## use dplyr to mutate and group
df %>%
    dplyr::mutate(referent = as.Date(referent)) %>%
    dplyr::group_by(difftime)
  

来源:本地数据框[25 x 4]       团体:difftime [19]

        col_1  col_2   referent difftime
       <date> <fctr>     <date>    <dbl>
1  2007-11-13      A 2007-11-13        0
2  2007-11-17      B 2007-11-13       -4
3  2007-11-19      C 2007-11-13       -6
4  2007-11-25      D 2007-11-13      -12
5  2007-11-28      E 2007-11-13      -15
6  2007-11-13      A 2007-11-17        4
7  2007-11-17      B 2007-11-17        0
8  2007-11-19      C 2007-11-17       -2
9  2007-11-25      D 2007-11-17       -8
10 2007-11-28      E 2007-11-17      -11
# ... with 15 more rows

答案 2 :(得分:1)

您可以使用基础R来快速完成此任务。

library(data.table)
df <- data.frame(col_1 = c('11/13/2007', '11/17/2007', '11/19/2007', '11/25/2007', '11/28/2007'),
                 col_2 = c('A', 'B', 'C', 'D', 'E'))

df$col_1 = as.Date(df$col_1, format = "%m/%d/%Y")

df$group = rleid(cumsum(c(0, diff.Date(df$col_1) > 5)))

> df
       col_1 col_2 group
1 2007-11-13     A     1
2 2007-11-17     B     1
3 2007-11-19     C     1
4 2007-11-25     D     2
5 2007-11-28     E     2