opensafely / covid-vaccine-effectiveness-sequential-vs-single

MIT License
3 stars 0 forks source link

Counting vaccinations after a positive test #2

Closed elsie-h closed 1 year ago

elsie-h commented 1 year ago

The code below (lines 690-755 in this script) is intended to extract the information to fill in the following sentences relating to the single trial approach:

Vaccination after a positive test was rare, occurring in xxx and xxx people who received BNT162b2 and ChAdOx1 respectively and in only xxx and xxx people respectively within 28 days after a positive test).

In the single trial cohort there were xxx person-years of follow-up (xxx while unvaccinated); during this time there were xxx positive tests (xxx while unvaccinated), xxx COVID-19 hospitalisations (xxx), and xxx deaths (xxx).

I'll email you the dummy data file to save you running everything (derived here, email because GitHub does not support .rds files).

events_single <- 
  read_rds(here("output", "single", "stset", "data_events.rds")) %>%
  as_tibble() %>%
  # remove intervals that start after maxfup
  filter(tstart < maxfup) %>%
  group_by(patient_id, vaxany1_status) %>%
  # calculate `min(tstart)` so that we can use `max` across all columns in `summarise()` below
  mutate(tstart = min(tstart)) %>%
  summarise(across(
    c(tstart, tstop, tte_postest, tte_covidadmitted, tte_death, tte_vaxany1, tte_vaxpfizer1, tte_vaxaz1),
    ~as.integer(max(.x))
  )) %>%
  # censor tstop at maxfup
  mutate(across(
    tstop, 
    ~if_else(.x > maxfup, as.integer(maxfup), .x)
  )) %>%
  # only keep tte_* such that tstart < tte_* <= tstop
  mutate(across(
    c(tte_postest, tte_covidadmitted, tte_death, tte_vaxany1, tte_vaxpfizer1, tte_vaxaz1),
    ~if_else(
      .x <= tstart | tstop < .x,
      NA_integer_,
      .x
    )
  )) %>%
  ungroup() 

events_single_summary <- events_single %>%
  mutate(
    vaxany1_postest_gap = tte_vaxany1 - tte_postest,
    vaxpfizer1_postest_gap = tte_vaxpfizer1 - tte_postest,
    vaxaz1_postest_gap = tte_vaxaz1 - tte_postest
  ) %>%
  group_by(vaxany1_status) %>%
  summarise(
    person_years = round(sum(tstop - tstart)/365.25,2),
    # first vaccine dose any time after a positive test
    # use >0 here rather than >=0, as we assume vaccination occurs at the start of the day and postest at the end
    vaxany1_after_postest = sum(vaxany1_postest_gap>0, na.rm=TRUE),
    # first vaccine dose within 28 days after a positive test
    vaxany1_after_postest_28 = sum(vaxany1_postest_gap>0 & vaxany1_postest_gap <= 28, na.rm=TRUE),
    # same restricted to pfizer
    vaxpfizer1_after_postest = sum(vaxpfizer1_postest_gap>0, na.rm=TRUE),
    vaxpfizer1_after_postest_28 = sum(vaxpfizer1_postest_gap>0 & vaxpfizer1_postest_gap <= 28, na.rm=TRUE),
    # same restricted to az
    vaxaz1_after_postest = sum(vaxaz1_postest_gap>0, na.rm=TRUE),
    vaxaz1_after_postest_28 = sum(vaxaz1_postest_gap>0 & vaxaz1_postest_gap <= 28, na.rm=TRUE),
    # number of outcomes
    postest = sum(!is.na(tte_postest)),
    covidadmitted = sum(!is.na(tte_covidadmitted)),
    death = sum(!is.na(tte_death))
  ) %>%
  ungroup()

events_single_summary <- events_single_summary %>%
  mutate(across(vaxany1_status, as.character)) %>%
  # add row for any vaxany1_status
  bind_rows(
    events_single_summary %>%
      mutate(vaxany1_status = "any") %>%
      group_by(vaxany1_status) %>%
      summarise(across(everything(), sum))
  ) %>%
  mutate(across(-vaxany1_status, roundmid_any, to=threshold))
wjchulme commented 1 year ago

Happy with this, all works and makes sense. Two minor things:

elsie-h commented 1 year ago

Thanks - good points - I've incorporated both changes in this commit.