Создать новую переменную на основе размера значения в другом столбце

Я пытаюсь создать df с новой переменной под названием «epi» (обозначает эпизод) ... которая основана на переменной «days.since.last». когда значение days.since.last больше 90, я хочу, чтобы переменная эпизода увеличивалась на 1.

Вот оригинальный df

   deid session.number days.since.last
1     1              1               0
2     1              2               7
3     1              3              12
4     5              1               0
5     5              2               7
6     5              3              14
7     5              4              93
8     5              5               5
9     5              6             102
10   12              1               0
11   12              2              21
12   12              3             104
13   12              4               4

Создано из

help <- data.frame(deid = c(1, 1, 1, 5, 5, 5, 5, 5, 5, 12, 12, 12, 12),
                   session.number = c(1, 2, 3, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4),
                   days.since.last = c(0, 7, 12, 0, 7, 14, 93, 5, 102, 0, 21, 104, 4))

Это результат, которого я надеюсь достичь

   deid session.number days.since.last epi
1     1              1               0   1
2     1              2               7   1
3     1              3              12   1
4     5              1               0   1
5     5              2               7   1
6     5              3              14   1
7     5              4              93   2
8     5              5               5   2
9     5              6             102   3
10   12              1               0   1
11   12              2              21   1
12   12              3             104   2
13   12              4               4   2

Моя лучшая попытка - это приведенный ниже код, однако он не меняет первое значение каждого нового эпизода (они остаются на 0) ...

help$epi <- as.numeric(0)

tmp <- gapply(help, form = ~ deid, FUN = function(x)
{     
  spanSeq <- rle(x$days.since.last <= 90)$lengths[rle(x$days.since.last <= 90)$values == TRUE] 
  x$epi[x$days.since.last <= 90] <- rep(seq_along(spanSeq), times = spanSeq)
  rm(spanSeq)
  x    
})
help2 <- do.call("rbind", tmp)
rownames(help2)<-c(1:length(help2$deid))

Любая помощь приветствуется!


person b222    schedule 09.06.2015    source источник


Ответы (1)


Вы можете сделать это с помощью dplyr вот так:

library(dplyr)
help %>% group_by(deid) %>% mutate(epi = cumsum(ifelse(days.since.last>90,1,0))+1)


   deid session.number days.since.last epi
1     1              1               0   1
2     1              2               7   1
3     1              3              12   1
4     5              1               0   1
5     5              2               7   1
6     5              3              14   1
7     5              4              93   2
8     5              5               5   2
9     5              6             102   3
10   12              1               0   1
11   12              2              21   1
12   12              3             104   2
13   12              4               4   2

По сути, group_by делает все по группам для вашей переменной deid. Мы присваиваем 1 или 0 каждому «days.since.last», превышающему 90. Затем мы создаем новую переменную, которая представляет собой совокупную сумму этих единиц и нулей. Добавив к нему еще один, мы получим желаемый результат.

person jalapic    schedule 09.06.2015
comment
help$epi <- with(help, ave(days.since.last, deid, FUN=function(x) cumsum(x>90)+1) ) - это базовый эквивалент R с использованием ave. - person thelatemail; 09.06.2015
comment
Блестяще. Спасибо, @jalapic. Ваше здоровье! - person b222; 09.06.2015
comment
Фактически, вы можете избавиться от ifelse в этом - это не нужно - логический TRUE/FALSE в любом случае эквивалентен 1/0 в целочисленной форме. - person thelatemail; 09.06.2015
comment
Аналогичный синтаксис с data.table setDT(help)[, epi:=cumsum(days.since.last>90)+1L , deid] - person akrun; 09.06.2015