Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: Up-counter with conditions

Tags:

r

dplyr

counter

I need a variable "minus_180_days"/(counter) to be numbered in ascending order:

  1. the first time you visit,

  2. if the second time has elapsed less than 180 days (compared to the previous visit for the patient); if the 180-day criterion is not met, a 1 must also appear on that second visit;

  3. if in the third visit less than 180 days have elapsed with the previous one (visit "2"), if the criterion of 180 days is not met, 1 in that third visit, etc

Data

pacient <- c(10,10,10,10,10,11,11,12,12,12,13, 13, 15, 14); pacient
date <- as.Date(c("01/01/2018","02/05/2018", "04/06/2018", "10/11/2019", "05/12/2018", "02/01/2018", "06/08/2018", "01/01/2018", "03/01/2018", "06/03/2018", "05/08/2018", "05/08/2019", "05/07/2019", "08/07/2017"), format = "%d/%m/%Y"); date 
DF <- data.frame(pacient, date); DF

I have this code

DF <- DF %>%
  group_by(pacient) %>%
  arrange(date) %>%
  mutate(days_visit = date - lag(date, default = first(date))) 
days_visit <- as.integer(DF$days_visit) 

DF <- DF[with(DF,order(pacient,date)),]

The output that I need (expected output) the output that I need

like image 207
Anne Avatar asked Dec 13 '25 01:12

Anne


2 Answers

A dplyr solution, updated to reflect @Gregor's useful comment:

DF2 <- DF %>%
  group_by(pacient) %>%
  arrange(pacient, date) %>%
  mutate(days_visit = (date - lag(date, default = first(date))) %>% as.integer,
         new_count = cumsum(days_visit > 180) + 1) %>%
  group_by(pacient, new_count) %>%
  mutate(vis_num = row_number(),
         counter = case_when(vis_num == 1      ~ 1L,
                             days_visit < 180  ~ vis_num,
                             TRUE              ~ 1L))
> DF
# A tibble: 14 x 5
# Groups:   pacient [6]
   pacient date       days_visit vis_num counter
     <dbl> <date>          <int>   <int>   <int>
 1      10 2018-01-01          0       1       1
 2      10 2018-05-02        121       2       2
 3      10 2018-06-04         33       3       3
 4      10 2018-12-05        184       4       1
 5      10 2019-11-10        340       5       1
 6      11 2018-01-02          0       1       1
 7      11 2018-08-06        216       2       1
 8      12 2018-01-01          0       1       1
 9      12 2018-01-03          2       2       2
10      12 2018-03-06         62       3       3
11      13 2018-08-05          0       1       1
12      13 2019-08-05        365       2       1
13      14 2017-07-08          0       1       1
14      15 2019-07-05          0       1       1
like image 54
Jon Spring Avatar answered Dec 14 '25 14:12

Jon Spring


A bit more concise way (adapted from @Gregor) do this based on tidyverse, including the fix to an error pointed by @Gregor.

DF %>%
  arrange(pacient, date) %>%
  group_by(pacient) %>%
  mutate(days_visit = as.integer(date - lag(date, default = first(date))) ,
         less_180 = days_visit < 180,
         counter = ave(less_180, cumsum(less_180 == 0), FUN = seq_along)) 

# A tibble: 17 x 5
# Groups:   pacient [6]
   pacient date       days_visit less_180 counter
     <dbl> <date>          <int>    <dbl>   <dbl>
 1      10 2018-01-01          0        1       1
 2      10 2018-05-02        121        1       2
 3      10 2018-06-04         33        1       3
 4      10 2018-12-05        184        0       1
 5      10 2019-11-10        340        0       1
 6      10 2019-11-11          1        1       2
 7      10 2019-11-12          1        1       3
 8      10 2019-11-13          1        1       4
 9      11 2018-01-02          0        1       1
10      11 2018-08-06        216        0       1
11      12 2018-01-01          0        1       1
12      12 2018-01-03          2        1       2
13      12 2018-03-06         62        1       3
14      13 2018-08-05          0        1       1
15      13 2019-08-05        365        0       1
16      14 2017-07-08          0        1       1
17      15 2019-07-05          0        1       1
like image 45
cropgen Avatar answered Dec 14 '25 14:12

cropgen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!