if (!require(pacman)) install.packages("pacman")
pacman::p_load(here, rio, magrittr, janitor, tidyverse, rstatix, gtsummary, huxtable,flextable, ggsurvfit, survival)
devtools::install_github("DahhamAlsoud/phdcocktail")
devtools::install_github("MSKCC-Epi-Bio/bstfun")
pacman::p_load(bstfun, phdcocktail)Real-world effectiveness and safety of risankizumab in patients with moderate-to-severe multi-refractory Crohn’s disease: a Belgian multi-centric cohort study
The aim of this analysis notebook is to reproduce the reported analysis in the paper Real-world effectiveness and safety of risankizumab in patients with moderate-to-severe multi-refractory Crohn's disease: a Belgian multi-centric cohort study.
To run the analysis, we assume that you already have the raw data file, named realworld-risankizumab-belgium.xlsx, in the input folder, within the home directory of your project.
This raw data file can be obtained upon reasonable request to the corresponding author, Marc Ferrante, via marc.ferrante@uzleuven.be.
1. Install and load needed packages, and write an S3 method for printing tables
print.data.frame <- function(df) {
df %>% flextable::flextable() %>% flextable::align(part = "all", align = "center") %>% flextable::autofit()
}
print.tabyl <- function(df) {
df %>% flextable::flextable() %>% flextable::align(part = "all", align = "center") %>% flextable::autofit()
}
print.tbl <- function(df) {
df %>% flextable::flextable() %>% flextable::align(part = "all", align = "center") %>% flextable::autofit()
}2. Import raw data
We will now import the raw data. There are 3 rows for each patient: baseline, week 24 and week 52. We will filter the dataframe to only the “baseline” rows as these contain the baseline characteristics, and the outcomes. We will also filter out excluded patients.
input_file <- import(here("input", "realworld-risankizumab-belgium.xlsx")) %>% clean_names()
input_file_baseline <- input_file[input_file$visit_timepoint == "baseline" & input_file$excluded == 0 ,]3. Pre-process raw data and get general info about the included cohort
Pre-process variables
We will transform some variables and generate some new ones which we will need later to construct our Table 1, or to be reported in the results/abstract.
continuous_vrs <- c("age_yrs", "age_at_diagnosis_yrs", "disease_duration_yrs", "bmi_kg_m2", "crp_mg_l", "calprotectin_ug_g", "ses_cd")
input_file_baseline %<>% mutate(across(all_of(continuous_vrs), ~ round(as.numeric(.), 1)))
input_file_baseline %<>% mutate(female_gender = if_else(gender == "F", 1, 0), .after = gender)
input_file_baseline %<>% mutate(current_smoker = if_else(smoking == 1, 1, 0), .after = smoking)
input_file_baseline %<>% mutate(age_montreal = case_when(
age_at_diagnosis_yrs < 17 ~ "A1",
age_at_diagnosis_yrs > 40 ~ "A3",
.default = "A2"
), .after = age_at_diagnosis_yrs)
input_file_baseline %<>% mutate(concomitant_cs = case_when(
concomitant_cs == "0" ~ "no",
str_detect(concomitant_cs, regex("medrol", ignore_case = TRUE)) ~ "sys",
.default = "top"
))
input_file_baseline %<>% mutate(concomitant_imm = if_else(concomitant_imm == "0", 0, 1))
input_file_baseline %<>% mutate(concomitant_5asa = if_else(concomitant_5asa == "0", 0, 1))
input_file_baseline %<>% mutate(concomitant_advanced = if_else(concomitant_advanced == "0", 0, 1))
input_file_baseline %<>% mutate(three_advanced = if_else(amount_previous_advanced > 2, 1, 0), .after = amount_previous_advanced)
input_file_baseline %<>% mutate(four_advanced = if_else(amount_previous_advanced > 3, 1, 0), .after = amount_previous_advanced)
input_file_baseline %<>% mutate(five_advanced = if_else(amount_previous_advanced > 4, 1, 0), .after = amount_previous_advanced)
input_file_baseline %<>% mutate(any_resection_before = if_else(previous_ileocaecal_resection == 1 | other_surgery_before == 1, 1, 0), .after = previous_ileocaecal_resection)Get general info about the included cohort
calculate number of included/excluded patients
input_file %>%
filter(visit_timepoint == "baseline") %>%
tabyl(excluded) %>%
adorn_pct_formatting(digits = 2) %>% print()excluded | n | percent |
|---|---|---|
0 | 69 | 93.24% |
1 | 5 | 6.76% |
calculate number of included patients with/without ostomy
input_file_baseline %>%
tabyl(stoma_at_start) %>%
adorn_pct_formatting(digits = 2) %>% print()stoma_at_start | n | percent |
|---|---|---|
0 | 55 | 79.71% |
1 | 14 | 20.29% |
calculate % female in the included cohort
input_file_baseline %>%
tabyl(gender) %>%
adorn_pct_formatting(digits = 2) %>% print()gender | n | percent |
|---|---|---|
F | 39 | 56.52% |
M | 30 | 43.48% |
calculate median age for the included cohort
print(report_quantiles(input_file_baseline, summary_vrs = "age_yrs"))median (IQR) age_yrs was 37.2 (29.5-49)
4. Present baseline characteristics (i.e. make Table 1)
We will define which variables we would like to include in our Table 1, recode them, and finally present them.
tableone_df <- input_file_baseline %>%
select(stoma_at_start, female_gender, age_yrs, disease_duration_yrs, current_smoker, bmi_kg_m2, crp_mg_l, calprotectin_ug_g, ses_cd, age_montreal,
disease_location, upper_gi_disease, disease_behaviour, peri_anal_disease, current_fibrostenosing, current_penetrating, any_resection_before,
concomitant_cs, concomitant_imm, concomitant_5asa, concomitant_advanced, three_advanced, four_advanced, five_advanced, previous_ustekinumab, reason_stop_ust)
tableone_df$stoma_at_start <- if_else(tableone_df$stoma_at_start == 0, "Without an ostomy", "With an ostomy") %>% factor(., levels = c("Without an ostomy", "With an ostomy"))
categorical_vrs = c("age_montreal", "disease_location", "disease_behaviour", "concomitant_cs", "reason_stop_ust")
tableone_df_recoded <- recode_vrs(tableone_df, data_dictionary = ibd_data_dict, vrs = categorical_vrs, factor = TRUE)
dichotomous_vrs <- base::setdiff(names(tableone_df), c(categorical_vrs, continuous_vrs))[-1]
theme_gtsummary_journal(journal = "jama")
theme_gtsummary_compact()
tableone <- tableone_df_recoded %>%
tbl_summary(by = stoma_at_start,
type = list(any_of(continuous_vrs) ~ "continuous",
any_of(categorical_vrs) ~ "categorical",
any_of(dichotomous_vrs) ~ "dichotomous"),
missing_text = "missing, n",
digits = list(all_categorical() ~ c(0, 1))) %>%
modify_header(label = "**Baseline characteristic**",
stat_1 = "**Without an ostomy<br />(n = 55)**",
stat_2 = "**With an ostomy<br />(n = 14)**")
tableone <- tableone %>%
add_variable_grouping(
"Previous number of advanced therapies, n (%)" = c("three_advanced", "four_advanced", "five_advanced")
)
labels_to_levels <- c("upper_gi_disease", "peri_anal_disease", "three_advanced", "four_advanced", "five_advanced")
tableone_body <- tableone[["table_body"]]
tableone_body$row_type[tableone_body$variable %in% labels_to_levels] <- "level"
tableone_body$stat_label[tableone_body$variable %in% labels_to_levels] <- NA
tableone_body <- tableone_body[tableone_body$label != "None",]
tableone_body <- tableone_body[-which(tableone_body$variable == "reason_stop_ust" & tableone_body$row_type == "missing"),]
tableone[["table_body"]] <- tableone_body
tableone <- tableone %>%
bold_labels() %>%
italicize_levels()
tableone| Baseline characteristic | Without an ostomy (n = 55) |
With an ostomy (n = 14) |
|---|---|---|
| Female, n (%) | 32 (58.2) | 7 (50.0) |
| Age (year), Median (IQR) | 39 (30 – 50) | 34 (26 – 43) |
| Disease duration (year), Median (IQR) | 17 (10 – 24) | 16 (11 – 21) |
| Current smoking, n (%) | 8 (14.8) | 2 (14.3) |
| missing, n | 1 | 0 |
| Body mass index (kg/m²), Median (IQR) | 23.6 (19.7 – 27.0) | 21.7 (18.9 – 24.1) |
| C-reactive protein (mg/L), Median (IQR) | 10 (4 – 25) | 21 (8 – 52) |
| missing, n | 6 | 1 |
| Faecal calprotectin (ug/g), Median (IQR) | 955 (484 – 1,800) | 1,038 (656 – 1,419) |
| missing, n | 30 | 12 |
| Simple endoscopic score for Crohn's disease, Median (IQR) | 10 (7 – 16) | 11 (8 – 19) |
| missing, n | 19 | 5 |
| Age at diagnosis (year), n (%) | ||
| < 17 years | 18 (32.7) | 8 (57.1) |
| 17-40 years | 30 (54.5) | 6 (42.9) |
| > 40 years | 7 (12.7) | 0 (0.0) |
| Disease location, n (%) | ||
| Ileal | 7 (12.7) | 1 (7.1) |
| Colonic | 9 (16.4) | 2 (14.3) |
| Ileocolonic | 39 (70.9) | 11 (78.6) |
| Upper GI modifier | 11 (20.0) | 3 (21.4) |
| Disease behaviour, n (%) | ||
| Inflammatory | 18 (32.7) | 3 (21.4) |
| Fibrostenotic | 25 (45.5) | 7 (50.0) |
| Penetrating | 12 (21.8) | 4 (28.6) |
| Perianal modifier | 24 (43.6) | 10 (71.4) |
| Current fibrostenosing complications, n (%) | 10 (18.2) | 4 (28.6) |
| Current penetrating complications, n (%) | 1 (1.8) | 1 (7.1) |
| Previous CD-related intestinal resection, n (%) | 33 (60.0) | 8 (57.1) |
| Concomitant corticosteroids, n (%) | ||
| Topical | 8 (14.5) | 1 (7.1) |
| Systemic | 10 (18.2) | 1 (7.1) |
| Concomitant immunomodulators, n (%) | 6 (10.9) | 3 (21.4) |
| Concomitant 5-aminosalicylates, n (%) | 2 (3.6) | 0 (0.0) |
| Concomitant advanced therapies, n (%) | 3 (5.5) | 2 (14.3) |
| Previous number of advanced therapies, n (%) | ||
| ≥ 3 | 52 (94.5) | 14 (100.0) |
| ≥ 4 | 46 (83.6) | 13 (92.9) |
| ≥ 5 | 16 (29.1) | 5 (35.7) |
| Previous ustekinumab, n (%) | 54 (98.2) | 14 (100.0) |
| Reason for ustekinumab discontinuation, n (%) | ||
| Loss of response | 34 (63.0) | 8 (57.1) |
| Primary non-response | 20 (37.0) | 3 (21.4) |
| Adverse events | 0 (0.0) | 3 (21.4) |
5. Survival analysis & dose optimizations
generate few “time” variables which we will need for further calculations
input_file_baseline %<>% mutate(persistence_duration = round(as.numeric(date_stop_or_surgery - visit_date, "weeks"), 1), .after = date_stop_or_surgery)
input_file_baseline %<>% mutate(time_to_optimize = round(as.numeric(date_dose_optimization - visit_date, "weeks"), 1), .after = date_dose_optimization)
input_file_baseline %<>% mutate(followup_duration = round(as.numeric(date_last_infusion - visit_date, "weeks"), 1), .after = date_last_infusion)calculate follow-up duration
print(report_quantiles(input_file_baseline, summary_vrs = "followup_duration"))median (IQR) followup_duration was 68.3 (51.9-98.4)
check how many patients stopped risankizumab and why
input_file_baseline %>%
tabyl(stop_current_treatment, reason_stop) %>% print()stop_current_treatment | LOF | LOR | PNR | NA_ |
|---|---|---|---|---|
0 | 0 | 0 | 0 | 54 |
1 | 2 | 7 | 6 | 0 |
calculate time to stop in patients with PNR/LOR
print(report_quantiles(input_file_baseline[input_file_baseline$reason_stop %in% c("LOR", "PNR"),], summary_vrs = "persistence_duration"))median (IQR) persistence_duration was 43.1 (29.6-55.9)
check how many of these stops were during the first 52 weeks of follow-up
input_file_baseline %>%
filter(stop_current_treatment == 1) %>%
count(reason_stop, during_w52 = followup_duration <=52) %>% print()reason_stop | during_w52 | n |
|---|---|---|
LOF | TRUE | 2 |
LOR | FALSE | 4 |
LOR | TRUE | 3 |
PNR | TRUE | 6 |
Survival analysis
construct KM curve
persistence_km <- survfit2(Surv(persistence_duration, stop_or_surgery) ~ 1, data = input_file_baseline) %>%
ggsurvfit(linewidth = 1) +
add_risktable() +
add_censor_mark() +
coord_cartesian(xlim = c(0,54), ylim = c(0.45, 1)) +
labs(x = "Follow-up time (weeks)", y = "Surgery-free survival percentage") +
scale_y_continuous(label = scales::percent,
breaks = seq(0, 1, by = 0.1),
expand = c(0.01, 0)) +
scale_x_continuous(breaks = seq(0, 54, by = 4),
expand = c(0.012, 0)) +
add_quantile(linetype = 2, x_value = 24) +
add_quantile(linetype = 2, x_value = 52) +
theme(panel.grid = element_blank(),
axis.title = element_text(face = "bold"))
persistence_kmcalculate survival probabilities
tbl_survfit <- survfit(Surv(persistence_duration, stop_or_surgery) ~ 1, input_file_baseline) %>%
tbl_survfit(
times = c(24, 52),
label_header = "**Week {time}**",
estimate_fun = function(x) style_percent(x, symbol = TRUE, digits = 1)
)
tbl_survfit| Characteristic | Week 24 | Week 52 |
|---|---|---|
| Overall | 92.8% (86.8% to 99.1%) | 75.2% (65.6% to 86.1%) |
Dose optimizations
check how many patients needed optimizations
input_file_baseline %>%
tabyl(dose_optimization) %>%
adorn_pct_formatting(digits = 2) %>% print()dose_optimization | n | percent |
|---|---|---|
0 | 50 | 72.46% |
1 | 19 | 27.54% |
calculate time to optimizations
print(report_quantiles(input_file_baseline, summary_vrs = "time_to_optimize"))median (IQR) time_to_optimize was 48.7 (33.5-61.5)
check how many of these optimizations were during the first 52 weeks of follow-up
input_file_baseline %>%
filter(dose_optimization == 1) %>%
count(during_w52 = time_to_optimize <= 52) %>% print()during_w52 | n |
|---|---|
FALSE | 7 |
TRUE | 12 |
6. Calculate and plot outcome data
in patients without ostomy
for clinical outcomes
calculate…
clinical_outcomes_without <- input_file_baseline %>%
filter(stoma_at_start == 0) %>%
select(clinical_outome_w24_itt, steroid_dependent_w24, clinical_outome_w52_itt, steroid_dependent_w52) %>%
mutate(clinical_response_w24 = if_else(clinical_outome_w24_itt != "pnr", 1, 0),
clinical_remission_w24 = if_else(clinical_outome_w24_itt == "rem", 1, 0),
clinical_response_w52 = if_else(clinical_outome_w52_itt != "pnr", 1, 0),
clinical_remission_w52 = if_else(clinical_outome_w52_itt == "rem", 1, 0), .keep = "unused")
clinical_outcomes_without %<>%
mutate(across(all_of(c("clinical_response_w24", "clinical_remission_w24")), ~ if_else(steroid_dependent_w24 == 1, 0, .), .names = "csfree_{.col}"),
.after = clinical_remission_w24) %>%
mutate(across(all_of(c("clinical_response_w52", "clinical_remission_w52")), ~ if_else(steroid_dependent_w52 == 1, 0, .), .names = "csfree_{.col}"),
.after = clinical_remission_w52) %>%
select(matches("clinical"))
clinical_outcomes_without_long <- clinical_outcomes_without %>%
summarise(across(matches("clinical"), ~ sum(. == 1, na.rm = T))) %>%
pivot_longer(cols = everything(),names_to = "outcome", values_to = "achieved") %>%
mutate(total= nrow(clinical_outcomes_without)) %>%
mutate(timepoint = if_else(str_detect(outcome, "24"), "Week 24", "Week 52"), .after = outcome) %>%
mutate(outcome = str_remove(outcome, "_w(\\d*)") %>%
str_replace_all(.,"_", " ") %>%
str_replace(., "csfree", "steroid-free") %>%
str_to_sentence()
) %>%
mutate(proportion = round_half_up(achieved/total, 3),
percentage = proportion*100,
percentage_labelled = scales::percent(proportion))
clinical_outcomes_without_long %<>% mutate(timepoint = factor(timepoint, levels = c("Week 24", "Week 52"))) %>%
mutate(outcome = factor(outcome, levels = c("Clinical response", "Steroid-free clinical response", "Clinical remission", "Steroid-free clinical remission")))
clinical_outcomes_without_long %>% print()outcome | timepoint | achieved | total | proportion | percentage | percentage_labelled |
|---|---|---|---|---|---|---|
Clinical response | Week 24 | 36 | 55 | 0.655 | 65.5 | 65.5% |
Clinical remission | Week 24 | 10 | 55 | 0.182 | 18.2 | 18.2% |
Steroid-free clinical response | Week 24 | 34 | 55 | 0.618 | 61.8 | 61.8% |
Steroid-free clinical remission | Week 24 | 10 | 55 | 0.182 | 18.2 | 18.2% |
Clinical response | Week 52 | 33 | 55 | 0.600 | 60.0 | 60.0% |
Clinical remission | Week 52 | 15 | 55 | 0.273 | 27.3 | 27.3% |
Steroid-free clinical response | Week 52 | 32 | 55 | 0.582 | 58.2 | 58.2% |
Steroid-free clinical remission | Week 52 | 15 | 55 | 0.273 | 27.3 | 27.3% |
then plot!
clinical_bars <- plot_bars(clinical_outcomes_without_long,outcome = outcome, proportion = proportion, percentage_labelled = percentage_labelled,
achieved = achieved, total = total, grouping = timepoint)for endoscopic outcomes
get the number of patients who had both baseline and follow-up endoscopy
input_file_baseline %<>%
mutate(baseANDfollowup_endoscopy = if_else(endoscopy_baseline == 1 & endoscopy_w24orw52 == 1, 1, 0), .after = endoscopy_w24orw52)
input_file_baseline %>%
group_by(stoma_at_start) %>%
summarise(baseline_endoscopy = sum(endoscopy_baseline == 1),
baseANDfollowup_endoscopy = sum(baseANDfollowup_endoscopy == 1)) %>% print()stoma_at_start | baseline_endoscopy | baseANDfollowup_endoscopy |
|---|---|---|
0 | 42 | 32 |
1 | 12 | 6 |
calculate…
endoscopic_outcomes_without <- input_file_baseline %>%
filter(stoma_at_start == 0, baseANDfollowup_endoscopy == 1) %>%
select(endoscopic_outcome_w24orw52) %>%
mutate(endoscopic_response = if_else(endoscopic_outcome_w24orw52 != "pnr", 1, 0),
endoscopic_remission = if_else(endoscopic_outcome_w24orw52 == "rem", 1, 0), .keep = "unused")
endoscopic_outcomes_without_long <- endoscopic_outcomes_without %>%
summarise(across(matches("endoscopic"), ~ sum(. == 1, na.rm = T))) %>%
pivot_longer(cols = everything(),names_to = "outcome", values_to = "achieved") %>%
mutate(total= nrow(endoscopic_outcomes_without)) %>%
mutate(outcome = str_replace_all(outcome,"_", " ") %>%
str_to_sentence()
) %>%
mutate(proportion = round_half_up(achieved/total, 3),
percentage = proportion*100,
percentage_labelled = scales::percent(proportion))
endoscopic_outcomes_without_long$outcome <- factor(endoscopic_outcomes_without_long$outcome, levels = c("Endoscopic response", "Endoscopic remission"))
endoscopic_outcomes_without_long %>% print()outcome | achieved | total | proportion | percentage | percentage_labelled |
|---|---|---|---|---|---|
Endoscopic response | 16 | 32 | 0.500 | 50.0 | 50% |
Endoscopic remission | 2 | 32 | 0.063 | 6.3 | 6% |
in patients with ostomy
for clinical outcomes
calculate…
clinical_outcomes_with<- input_file_baseline %>%
filter(stoma_at_start == 1) %>%
select(clinical_outome_w24_itt, steroid_dependent_w24, clinical_outome_w52_itt, steroid_dependent_w52) %>%
mutate(clinical_response_w24 = if_else(clinical_outome_w24_itt != "pnr", 1, 0),
clinical_remission_w24 = if_else(clinical_outome_w24_itt == "rem", 1, 0),
clinical_response_w52 = if_else(clinical_outome_w52_itt != "pnr", 1, 0),
clinical_remission_w52 = if_else(clinical_outome_w52_itt == "rem", 1, 0), .keep = "unused")
clinical_outcomes_with%<>%
mutate(across(all_of(c("clinical_response_w24", "clinical_remission_w24")), ~ if_else(steroid_dependent_w24 == 1, 0, .), .names = "csfree_{.col}"),
.after = clinical_remission_w24) %>%
mutate(across(all_of(c("clinical_response_w52", "clinical_remission_w52")), ~ if_else(steroid_dependent_w52 == 1, 0, .), .names = "csfree_{.col}"),
.after = clinical_remission_w52) %>%
select(matches("clinical"))
clinical_outcomes_with_long <- clinical_outcomes_with%>%
summarise(across(matches("clinical"), ~ sum(. == 1, na.rm = T))) %>%
pivot_longer(cols = everything(),names_to = "outcome", values_to = "achieved") %>%
mutate(total= nrow(clinical_outcomes_with)) %>%
mutate(timepoint = if_else(str_detect(outcome, "24"), "Week 24", "Week 52"), .after = outcome) %>%
mutate(outcome = str_remove(outcome, "_w(\\d*)") %>%
str_replace_all(.,"_", " ") %>%
str_replace(., "csfree", "steroid-free") %>%
str_to_sentence()
) %>%
mutate(proportion = round_half_up(achieved/total, 3),
percentage = proportion*100,
percentage_labelled = scales::percent(proportion))
clinical_outcomes_with_long %<>% mutate(timepoint = factor(timepoint, levels = c("Week 24", "Week 52"))) %>%
mutate(outcome = factor(outcome, levels = c("Clinical response", "Steroid-free clinical response", "Clinical remission", "Steroid-free clinical remission")))
clinical_outcomes_with_long %>% print()outcome | timepoint | achieved | total | proportion | percentage | percentage_labelled |
|---|---|---|---|---|---|---|
Clinical response | Week 24 | 7 | 14 | 0.500 | 50.0 | 50.0% |
Clinical remission | Week 24 | 1 | 14 | 0.071 | 7.1 | 7.1% |
Steroid-free clinical response | Week 24 | 7 | 14 | 0.500 | 50.0 | 50.0% |
Steroid-free clinical remission | Week 24 | 1 | 14 | 0.071 | 7.1 | 7.1% |
Clinical response | Week 52 | 6 | 14 | 0.429 | 42.9 | 42.9% |
Clinical remission | Week 52 | 2 | 14 | 0.143 | 14.3 | 14.3% |
Steroid-free clinical response | Week 52 | 6 | 14 | 0.429 | 42.9 | 42.9% |
Steroid-free clinical remission | Week 52 | 2 | 14 | 0.143 | 14.3 | 14.3% |
for endoscopic outcomes
get the number of patients who had both baseline and follow-up endoscopy
input_file_baseline %>%
group_by(stoma_at_start) %>%
summarise(baseline_endoscopy = sum(endoscopy_baseline == 1),
baseANDfollowup_endoscopy = sum(baseANDfollowup_endoscopy == 1)) %>% print()stoma_at_start | baseline_endoscopy | baseANDfollowup_endoscopy |
|---|---|---|
0 | 42 | 32 |
1 | 12 | 6 |
calculate…
endoscopic_outcomes_with <- input_file_baseline %>%
filter(stoma_at_start == 1, baseANDfollowup_endoscopy == 1) %>%
select(endoscopic_outcome_w24orw52) %>%
mutate(endoscopic_response = if_else(endoscopic_outcome_w24orw52 != "pnr", 1, 0),
endoscopic_remission = if_else(endoscopic_outcome_w24orw52 == "rem", 1, 0), .keep = "unused")
endoscopic_outcomes_with_long <- endoscopic_outcomes_with %>%
summarise(across(matches("endoscopic"), ~ sum(. == 1, na.rm = T))) %>%
pivot_longer(cols = everything(),names_to = "outcome", values_to = "achieved") %>%
mutate(total= nrow(endoscopic_outcomes_with)) %>%
mutate(outcome = str_replace_all(outcome,"_", " ") %>%
str_to_sentence()
) %>%
mutate(proportion = round_half_up(achieved/total, 3),
percentage = proportion*100,
percentage_labelled = scales::percent(proportion))
endoscopic_outcomes_with_long$outcome <- factor(endoscopic_outcomes_with_long$outcome, levels = c("Endoscopic response", "Endoscopic remission"))
endoscopic_outcomes_with_long %>% print()outcome | achieved | total | proportion | percentage | percentage_labelled |
|---|---|---|---|---|---|
Endoscopic response | 4 | 6 | 0.667 | 66.7 | 67% |
Endoscopic remission | 4 | 6 | 0.667 | 66.7 | 67% |