Search code examples
rregressionstatasurvival-analysis

Is there a R function for preparing datasets for survival analysis like stset in Stata?


Datasets look like this

id  start   end  failure x1
 1    0      1      0    0
 1    1      3      0    0
 1    3      6      1    0
 2    0      1      1    1
 2    1      3      1    1
 2    3      4      0    1
 2    4      6      0    1
 2    6      7      1    1

As you see, when id = 1, it's just the data input to coxph in survival package. However, when id = 2, at the beginning and end, failure occurs, but in the middle, failure disappears.

Is there a general function to extract data from id = 2 and get the result like id = 1?

I think when id = 2, the result should look like below.

id  start   end  failure x1
1    0      1      0    0
1    1      3      0    0
1    3      6      1    0
2    3      4      0    1
2    4      6      0    1
2    6      7      1    1


Solution

  • A bit hacky, but should get the job done.

    Data:

    # Load data
    library(tidyverse)
    df <- read_table("
     id   start  end    failure  x1
     1    0      1      0        0
     1    1      3      0        0
     1    3      6      1        0
     2    0      1      1        1
     2    1      3      1        1
     2    3      4      0        1
     2    4      6      0        1
     2    6      7      1        1
    ") 
    

    Data wrangling:

    # Check for sub-groups within IDs and remove all but the last one
    df <- df %>%
        # Group by ID
        group_by(
            id
        ) %>%
        mutate(
            # Check if a new sub-group is starting (after a failure)
            new_group = case_when(
                # First row is always group 0
                row_number() == 1 ~ 0,
                # If previous row was a failure, then a new sub-group starts here
                lag(failure) == 1 ~ 1,
                # Otherwise not
                TRUE ~ 0
            ),
            # Assign sub-group number by calculating cumulative sums
            group = cumsum(new_group)
        ) %>%
        # Keep only last sub-group for each ID
        filter(
            group == max(group)
        ) %>%
        ungroup() %>%
        # Remove working columns
        select(
            -new_group, -group
        )
    

    Result:

    > df
    # A tibble: 6 × 5
         id start   end failure    x1
      <dbl> <dbl> <dbl>   <dbl> <dbl>
    1     1     0     1       0     0
    2     1     1     3       0     0
    3     1     3     6       1     0
    4     2     3     4       0     1
    5     2     4     6       0     1
    6     2     6     7       1     1