根据多种条件匹配数据框的行

时间:2019-04-10 07:55:24

标签: r dplyr

我有一个数据框,其中包含不同单位的活动以及这些活动的开始和结束日期。我需要知道是否有单位在结束一项活动后的31天内开始了一项新活动,这些活动是什么(其ID)。

我尝试使用dplyr软件包:具体来说,我先使用group_by(unit)然后总结一下,但是我看不出如何得到答案。

# Dataframe
unit <- rep(LETTERS[1:4], c(2,2,3,3))
start <- as.Date(c("2017-02-28", "2018-03-26", "2017-08-01", "2018-01-23", "2016-08-29", "2016-12-12", "2017-04-12", "2016-11-01", "2016-11-08", "2017-04-03"))
end <- as.Date(c("2018-12-31", "2018-12-31", "2017-12-31", "2018-10-23", "2017-03-31", "2017-12-31", "2019-02-28", "2017-03-31", "2017-03-31", "2018-08-31"))

DF <- data.frame(unit, start, end)
> DF
   unit      start        end
1     A 2017-02-28 2018-12-31
2     A 2018-03-26 2018-12-31
3     B 2017-08-01 2017-12-31
4     B 2018-01-23 2018-10-23
5     C 2016-08-29 2017-03-31
6     C 2016-12-12 2017-12-31
7     C 2017-04-12 2019-02-28
8     D 2016-11-01 2017-03-31
9     D 2016-11-08 2017-03-31
10    D 2017-04-03 2018-08-31

我想要获得的输出将是这样的数据帧:

   unit      activity1        activity2
1     B              3               4
2     C              5               7
3     D              8              10
4     D              9              10

1 个答案:

答案 0 :(得分:0)

西蒙!

在您的示例中活动4实际上在活动6结束后不到31天开始,但是未在您期望的结果中列出-我想是因为这些活动属于不同的单元。

因此,我假设您想获得每单位的结果。您可以这样:

DF$no <- 1:nrow(DF)
spl <- split[DF, DF$unit]
output <- do.call(rbind, 
        lapply(split(DF, DF$unit), function(x){
          unit.activities <- c()
          for (i in 1:nrow(x)) {
            delta_end <- difftime(x$start[i], x$end)
            ended_last_month <- which(delta_end>=0 & delta_end<=31)
            if (length(ended_last_month)>0) {
              return(do.call(rbind, lapply(ended_last_month, function(j){c(as.character(x$unit[i]), x$no[j], x$no[i])})))
            }
          }
          return(as.data.frame(unit.activities))
        })
        )
names(output) <- c('unit', 'activity1', 'activity2')
rownames(output) <- 1:nrow(output)

> output
  unit activity1 activity2
1    B         3         4
2    C         5         7
3    D         8        10
4    D         9        10