Скользящая разница в group_by в R - PullRequest
3 голосов
/ 07 января 2020

У меня есть набор данных gap, который записывает детали задач, которые люди выполняют за год. Это выглядит так:

ID       start.day       end.day
A         147             158   
A         194             210
B         2               87
B         98              283
C         313             317
D         32              87  

Я хочу вычислить среднее время разрыва между задачами людей. Так что я делаю это как gap %>% group_by(ID)%>% mutate(gap_time, lag(start.day, n=1) - end.day). Но это дает мне -208 в 3-й строке, так как это 2 с начала.дня B - 210 с конца.дня A.

Я хочу что-то подобное ниже, и хочу создать timemark для последовательности gap_time. Как мне быть?

ID       start.day       end.day       gap_time      timemark
A         147             158          NA            NA 
A         194             210          36            1
B         2               87           NA            NA
B         98              283          11            1
C         313             317          NA            NA
D         32              87           NA            NA

Ответы [ 3 ]

3 голосов
/ 07 января 2020

Вы можете проверить, равен ли ID поднабором с -1 и -nrow(gap), а также рассчитать gap_time с этим.

gap$gap_time <- gap$start.day - c(NA, gap$end.day[-nrow(gap)])
gap$timemark <- c(FALSE, gap$ID[-1] == gap$ID[-nrow(gap)])
gap$gap_time[!gap$timemark]  <- NA
#  ID start.day end.day gap_time timemark
#1  A       147     158       NA    FALSE
#2  A       194     210       36     TRUE
#3  B         2      87       NA    FALSE
#4  B        98     283       11     TRUE
#5  C       313     317       NA    FALSE
#6  D        32      87       NA    FALSE

В случае, если gap$ID является коэффициент, который вы также можете использовать:

gap$gap_time <- c(NA, gap$start.day[-1] - gap$end.day[-nrow(gap)])
gap$timemark <- c(0,diff(unclass(gap$ID)))
gap$gap_time[gap$timemark==0]  <- NA

Или вы можете использовать ave:

gap$gap_time <- ave(gap$start.day - c(NA, gap$end.day[-nrow(gap)]), gap$ID
                  , FUN=function(x) "[<-"(x,1,NA))
3 голосов
/ 07 января 2020

Может быть, это поможет

library(dplyr)
gap %>% 
   group_by(ID) %>% 
   mutate(gap_time = start.day - lag(end.day), timemark = NA^is.na(gap_time))

data

gap <- structure(list(ID = c("A", "A", "B", "B", "C", "D"), start.day = c(147L, 
194L, 2L, 98L, 313L, 32L), end.day = c(158L, 210L, 87L, 283L, 
317L, 87L)), class = "data.frame", row.names = c(NA, -6L))
1 голос
/ 08 января 2020

Вот еще одно базовое решение R в дополнение к ответу @ GKi

lst <- lapply(split(gap, gap$ID), function(v) {
  if (nrow(v)==1) gap_time <-  NA
  else gap_time <- c(NA,v[-1,"start.day"]- v[-nrow(v),"end.day"])
  data.frame(v,gap_time = gap_time, timemark = ifelse(is.na(gap_time),NA,1))
})
gapout <- do.call(rbind,c(lst,make.row.names = F))

таким, что

> gapout
  ID start.day end.day gap_time timemark
1  A       147     158       NA       NA
2  A       194     210       36        1
3  B         2      87       NA       NA
4  B        98     283       11        1
5  C       313     317       NA       NA
6  D        32      87       NA       NA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...