snap <- fread("snap_audit.csv",
na.strings = c(
"Not available frominformation available",
"Not available from information available",
"Not clear from information available",
"Unclear",
"Not Clear from the information available",
"",
" ",
"Not clear fro the information available",
"Not clear from the information available",
"NA",
"na",
"N/A"
)) %>%
as_tibble() %>%
janitor::clean_names() %>%
subset(select = -c(ip,
who_are_you)) %>%
mutate(
submission_id = 1:n()
)
## Warning in fread("snap_audit.csv", na.strings = c("Not available
## frominformation available", : na.strings[7]==" " consists only of whitespace,
## ignoring. strip.white==TRUE (default) and "" is present in na.strings, so any
## number of spaces in string columns will already be read as <NA>.
outcomes <- snap %>%
subset(
select = c(
submission_id,
at_follow_up_did_the_patient_describe_ongoing_pain,
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
at_follow_up_did_the_patient_describe_penile_curvature,
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
were_there_any_early_complications_clavien_dindo_3
)
) %>%
mutate(good_outcome = case_when(
at_follow_up_did_the_patient_describe_ongoing_pain == "No" &
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up == "No" &
at_follow_up_did_the_patient_describe_penile_curvature == "No" &
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening == "No" &
were_there_any_early_complications_clavien_dindo_3 == "No" ~ "Yes",
at_follow_up_did_the_patient_describe_ongoing_pain == "Yes" |
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up == "Yes" |
at_follow_up_did_the_patient_describe_penile_curvature == "Yes" |
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening == "Yes" |
were_there_any_early_complications_clavien_dindo_3 == "Yes" ~ "No",
TRUE ~ NA_character_
))
plot_missing(outcomes)
outcomes %>%
drop_na(at_follow_up_did_the_patient_describe_ongoing_pain) %>%
filter(at_follow_up_did_the_patient_describe_ongoing_pain != "No follow up" &
at_follow_up_did_the_patient_describe_ongoing_pain != "No Follow up" &
at_follow_up_did_the_patient_describe_ongoing_pain != "Not from the information available") %>%
tabyl(at_follow_up_did_the_patient_describe_ongoing_pain) %>%
mutate(
Pain = at_follow_up_did_the_patient_describe_ongoing_pain,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c(Pain,
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Pain | n | Percent |
|---|---|---|
| No | 130 | 82 |
| Yes | 28 | 18 |
outcomes %>%
drop_na(did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up) %>%
subset(did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up != "No follow up") %>%
tabyl(did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up) %>%
mutate(
"New/Worsening ED" = did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("New/Worsening ED",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| New/Worsening ED | n | Percent |
|---|---|---|
| No | 113 | 74 |
| Yes - Manageable with medication | 23 | 15 |
| Yes - Still bothersome despite medication | 5 | 3 |
| Yes - Unable to quantify from information available | 11 | 7 |
outcomes %>%
drop_na(at_follow_up_did_the_patient_describe_penile_curvature) %>%
subset(at_follow_up_did_the_patient_describe_penile_curvature != "No follow up") %>%
tabyl(at_follow_up_did_the_patient_describe_penile_curvature) %>%
mutate(
"Penile Curvature" = at_follow_up_did_the_patient_describe_penile_curvature,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Penile Curvature",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Penile Curvature | n | Percent |
|---|---|---|
| No | 104 | 72 |
| Yes - Able to have penetrative intercourse | 35 | 24 |
| Yes - Not clear if limiting penetrative intercourse | 5 | 3 |
outcomes %>%
drop_na(at_follow_up_was_there_evidence_of_penile_wasting_or_shortening) %>%
subset(at_follow_up_was_there_evidence_of_penile_wasting_or_shortening != "No follow up") %>%
tabyl(at_follow_up_was_there_evidence_of_penile_wasting_or_shortening) %>%
mutate(
"Penile Waisting / Shortening" = at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Penile Waisting / Shortening",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Penile Waisting / Shortening | n | Percent |
|---|---|---|
| No | 114 | 87 |
| Yes | 17 | 13 |
outcomes %>%
drop_na(were_there_any_early_complications_clavien_dindo_3) %>%
tabyl(were_there_any_early_complications_clavien_dindo_3) %>%
mutate(
"Clavien Dindo >/= III" = were_there_any_early_complications_clavien_dindo_3,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Clavien Dindo >/= III",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Clavien Dindo >/= III | n | Percent |
|---|---|---|
| No | 245 | 98 |
| Yes | 5 | 2 |
outcomes %>%
drop_na(good_outcome) %>%
tabyl(good_outcome) %>%
mutate(
"Composite Good Outcome" = good_outcome,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Composite Good Outcome",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Composite Good Outcome | n | Percent |
|---|---|---|
| No | 46 | 46 |
| Yes | 53 | 54 |
There are some dates that appear to be prior to audit
collection?
snap <- snap %>%
rowwise() %>%
mutate(
what_was_the_estimated_date_and_time_of_injury = case_when(
str_detect(what_was_the_estimated_date_and_time_of_injury, ":") ~
dmy_hm(what_was_the_estimated_date_and_time_of_injury),
TRUE ~ dmy(what_was_the_estimated_date_and_time_of_injury) + hours(12)
),
what_age_was_the_patient_at_the_time_of_the_injury = as.integer(what_age_was_the_patient_at_the_time_of_the_injury),
mechanism_of_injury = as.factor(mechanism_of_injury),
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved = as.factor(
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved
),
did_the_patient_have_a_history_of_a_prior_penile_fracture = as.factor(did_the_patient_have_a_history_of_a_prior_penile_fracture),
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional = case_when(
str_detect(
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional,
":"
) ~
dmy_hm(
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional
),
TRUE ~ dmy(
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional
) + hours(12)
),
was_pain_present_at_presentation = as.factor(was_pain_present_at_presentation),
was_there_immediate_detumescence_loss_of_erection = as.factor(was_there_immediate_detumescence_loss_of_erection),
was_an_audible_pop_reported_by_the_patient = as.factor(was_an_audible_pop_reported_by_the_patient),
was_penile_bruising_present = as.factor(was_penile_bruising_present),
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary = as.factor(
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary
),
was_there_a_suspicion_of_urethral_injury_at_presentation = as.factor(was_there_a_suspicion_of_urethral_injury_at_presentation),
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply = as.factor(
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply
),
was_imaging_performed_if_so_what_imaging_select_all_that_apply = as.factor(
was_imaging_performed_if_so_what_imaging_select_all_that_apply
),
was_the_patient_transferred_between_hospitals_for_specialist_imaging = as.factor(
was_the_patient_transferred_between_hospitals_for_specialist_imaging
),
did_the_reporting_radiologist_have_a_specialist_interest_in_urology = as.factor(
did_the_reporting_radiologist_have_a_specialist_interest_in_urology
),
what_time_did_surgical_repair_take_place_knife_to_skin = case_when(
str_detect(what_time_did_surgical_repair_take_place_knife_to_skin, ":") ~
dmy_hm(what_time_did_surgical_repair_take_place_knife_to_skin),
TRUE ~ dmy(what_time_did_surgical_repair_take_place_knife_to_skin) + hours(12)
),
did_the_patient_get_to_theatre_within_24_hours_of_injury = as.factor(did_the_patient_get_to_theatre_within_24_hours_of_injury),
did_the_patient_get_to_theatre_within_24_hours_of_presentation = as.factor(
did_the_patient_get_to_theatre_within_24_hours_of_presentation
),
was_the_patient_transferred_from_another_hospital_for_surgical_repair = as.factor(
was_the_patient_transferred_from_another_hospital_for_surgical_repair
),
were_antibiotics_given_at_induction = as.factor(were_antibiotics_given_at_induction),
was_a_consultant_present_in_theatre = as.factor(was_a_consultant_present_in_theatre),
was_a_trainee_present_in_theatre = as.factor(was_a_trainee_present_in_theatre),
what_was_the_grade_of_the_primary_surgeon = as.factor(what_was_the_grade_of_the_primary_surgeon),
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology = as.factor(
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology
),
was_a_urologist_with_a_specialist_interest_in_andrology_present_in_theatre = as.factor(
was_a_urologist_with_a_specialist_interest_in_andrology_present_in_theatre
),
where_was_the_site_of_the_fracture_answer_all_that_apply = as.factor(where_was_the_site_of_the_fracture_answer_all_that_apply),
what_incision_was_made = as.factor(what_incision_was_made),
was_a_concurrent_circumcision_performed = as.factor(was_a_concurrent_circumcision_performed),
what_suture_was_used_for_the_repair_of_the_tunical_fracture = as.factor(
what_suture_was_used_for_the_repair_of_the_tunical_fracture
),
were_intraoperative_urethral_investigations_performed_select_all_that_apply = as.factor(
were_intraoperative_urethral_investigations_performed_select_all_that_apply
),
was_a_urethral_injury_noted_at_surgery = as.factor(was_a_urethral_injury_noted_at_surgery),
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra = as.factor(
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra
),
were_there_any_early_complications_clavien_dindo_3 = as.factor(were_there_any_early_complications_clavien_dindo_3),
if_early_complications_occurred_what_were_they = as.factor(if_early_complications_occurred_what_were_they),
if_other_complications_occurred_please_specify_enter_na_if_not_relevant = as.factor(
if_other_complications_occurred_please_specify_enter_na_if_not_relevant
),
was_follow_up_arranged = as.factor(was_follow_up_arranged),
when_was_follow_up_if_organised_if_no_follow_up_enter_01_01_2000 = dmy(
when_was_follow_up_if_organised_if_no_follow_up_enter_01_01_2000
),
was_follow_up_arranged_with_a_urologist_with_an_interest_in_andrology = as.factor(
was_follow_up_arranged_with_a_urologist_with_an_interest_in_andrology
),
presentation_to_knife_to_skin = hms(presentation_to_knife_to_skin),
# Outcomes
at_follow_up_did_the_patient_describe_ongoing_pain = factor(
at_follow_up_did_the_patient_describe_ongoing_pain,
levels = c("Yes", "No", "No Follow up", "Not from the information available")
),
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up = factor(
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
levels = c(
"Yes - Unable to quantify from information available",
"Yes - Manageable with medication",
"Yes - Still bothersome despite medication",
"No",
"No follow up"
)
),
at_follow_up_did_the_patient_describe_penile_curvature = factor(
at_follow_up_did_the_patient_describe_penile_curvature,
levels = c(
"Yes - Able to have penetrative intercourse",
"Yes - Not clear if limiting penetrative intercourse",
"No",
"No follow up"
)
),
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening = factor(
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
levels = c("Yes", "No", "No follow up")
),
laterality = case_when(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("left", ignore_case = TRUE)) &
!str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("right", ignore_case = TRUE)) ~ "Unilateral",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("right", ignore_case = TRUE)) &
!str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("left", ignore_case = TRUE)) ~ "Unilateral",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("left", ignore_case = TRUE)) &
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, regex("right", ignore_case = TRUE)) ~ "Bilateral",
TRUE ~ NA_character_
),
n_locations = sum(c(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Distal"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Mid"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Proximal"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Crura")
)),
locality = case_when(
n_locations >= 2 ~ "Multi-level",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Distal") ~ "Distal",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Mid") ~ "Mid",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Proximal") ~ "Proximal",
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Crura") ~ "Crura",
TRUE ~ NA_character_
),
# Other
are_there_any_other_comments_you_would_like_to_make_regarding_the_case = as.character(
are_there_any_other_comments_you_would_like_to_make_regarding_the_case
),
.keep = "all"
) %>%
select(
what_was_the_estimated_date_and_time_of_injury,
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional,
what_time_did_surgical_repair_take_place_knife_to_skin,
everything()
) %>%
select(-n_locations)
## Warning: There were 799 warnings in `mutate()`.
## The first warning was:
## ℹ In argument: `what_was_the_estimated_date_and_time_of_injury =
## case_when(...)`.
## ℹ In row 1.
## Caused by warning:
## ! All formats failed to parse. No formats found.
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 798 remaining warnings.
outcomes <- snap %>%
subset(
select = c(
submission_id,
at_follow_up_did_the_patient_describe_ongoing_pain,
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
at_follow_up_did_the_patient_describe_penile_curvature,
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
were_there_any_early_complications_clavien_dindo_3
)
) %>%
mutate(good_outcome = case_when(
at_follow_up_did_the_patient_describe_ongoing_pain == "No" &
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up == "No" &
at_follow_up_did_the_patient_describe_penile_curvature == "No" &
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening == "No" &
were_there_any_early_complications_clavien_dindo_3 == "No" ~ "Yes",
at_follow_up_did_the_patient_describe_ongoing_pain == "Yes" |
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up == "Yes" |
at_follow_up_did_the_patient_describe_penile_curvature == "Yes" |
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening == "Yes" |
were_there_any_early_complications_clavien_dindo_3 == "Yes" ~ "No",
TRUE ~ NA_character_
))
predictors <- snap %>%
subset(
select = -c(
at_follow_up_did_the_patient_describe_ongoing_pain,
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
at_follow_up_did_the_patient_describe_penile_curvature,
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
if_other_complications_occurred_please_specify_enter_na_if_not_relevant,
if_early_complications_occurred_what_were_they,
were_there_any_early_complications_clavien_dindo_3,
are_there_any_other_comments_you_would_like_to_make_regarding_the_case,
was_follow_up_arranged_with_a_urologist_with_an_interest_in_andrology,
when_was_follow_up_if_organised_if_no_follow_up_enter_01_01_2000
)
)
plot_missing(predictors)
ggplot(predictors, aes(x = what_age_was_the_patient_at_the_time_of_the_injury)) +
geom_histogram(bins = 50, fill = "skyblue", color = "black") +
labs(
title = "Histogram of Age at Time of Injury",
x = "Age (years)",
y = "Count"
) +
theme_minimal()
## Warning: Removed 1 row containing non-finite outside the scale range
## (`stat_bin()`).
ggplot(predictors, aes(x = what_age_was_the_patient_at_the_time_of_the_injury)) +
geom_density(fill = "skyblue", color = "black") +
labs(
title = "Density Plot of Age at Time of Injury",
x = "Age (years)",
y = "Count"
) +
theme_minimal()
## Warning: Removed 1 row containing non-finite outside the scale range
## (`stat_density()`).
predictors %>%
drop_na(what_suture_was_used_for_the_repair_of_the_tunical_fracture) %>%
tabyl(what_suture_was_used_for_the_repair_of_the_tunical_fracture) %>%
mutate(
"Type of Suture" = what_suture_was_used_for_the_repair_of_the_tunical_fracture,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Type of Suture",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Type of Suture | n | Percent |
|---|---|---|
| PDS 3-0 Suture | 46 | 19 |
| PDS 2-0 Suture | 93 | 38 |
| Vicryl 3-0 Suture | 5 | 2 |
| Other | 30 | 12 |
| Nylon 4-0 Suture | 1 | 0 |
| PDS 0-Suture | 37 | 15 |
| Vicryl 4-0 Suture | 3 | 1 |
| PDS 1-0 Suture | 4 | 2 |
| PDS 4-0 Suture | 10 | 4 |
| Vicryl 2-0 Suture | 10 | 4 |
| Vicryl 0 -Suture | 2 | 1 |
| PDS 2-0 Suture - Vicryl 3-0 Suture | 1 | 0 |
| PDS 0-Suture - PDS 2-0 Suture | 2 | 1 |
| Nylon 3-0 Suture | 1 | 0 |
| PDS 2-0 Suture - Vicryl 2-0 Suture | 1 | 0 |
predictors <- predictors %>%
mutate(
type_of_suture = case_when(
str_detect(
what_suture_was_used_for_the_repair_of_the_tunical_fracture,
"PDS"
) ~ "Non-absorbable",
str_detect(
what_suture_was_used_for_the_repair_of_the_tunical_fracture,
"Nylon"
) ~ "Non-absorbable",
str_detect(
what_suture_was_used_for_the_repair_of_the_tunical_fracture,
"Vicryl"
) ~ "Absorbable",
what_suture_was_used_for_the_repair_of_the_tunical_fracture == "Other" |
what_suture_was_used_for_the_repair_of_the_tunical_fracture == "PDS 2-0 Suture - Vicryl 2-0 Suture" ~ "Unclear",
TRUE ~ NA_character_
)
)
predictors %>%
select(type_of_suture) %>%
group_by(type_of_suture) %>%
summarise(
n = n(),
"Percentage (%)" = round(n / 258 * 100)
) %>%
gt() %>%
gt_theme_espn()
| type_of_suture | n | Percentage (%) |
|---|---|---|
| Absorbable | 20 | 8 |
| Non-absorbable | 196 | 76 |
| Unclear | 30 | 12 |
| NA | 12 | 5 |
predictors %>%
drop_na(was_a_urethral_injury_noted_at_surgery) %>%
tabyl(was_a_urethral_injury_noted_at_surgery) %>%
mutate(
"Urethral Injury?" = was_a_urethral_injury_noted_at_surgery,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Urethral Injury?",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Urethral Injury? | n | Percent |
|---|---|---|
| No | 200 | 80 |
| Yes | 51 | 20 |
predictors %>%
drop_na(did_the_patient_have_a_history_of_a_prior_penile_fracture) %>%
tabyl(did_the_patient_have_a_history_of_a_prior_penile_fracture) %>%
mutate(
"Prior Penile Fracture?" = did_the_patient_have_a_history_of_a_prior_penile_fracture,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Prior Penile Fracture?",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Prior Penile Fracture? | n | Percent |
|---|---|---|
| No | 233 | 93 |
| Yes | 18 | 7 |
predictors %>%
drop_na(mechanism_of_injury) %>%
tabyl(mechanism_of_injury) %>%
mutate(
"Mechanism of Injury" = mechanism_of_injury,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Mechanism of Injury",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Mechanism of Injury | n | Percent |
|---|---|---|
| Sexual intercourse trauma | 214 | 86 |
| Other | 6 | 2 |
| Non-sexual blunt force trauma | 19 | 8 |
| Masturbation injury | 10 | 4 |
This could be amalgamated with Mechanism of injury
predictors %>%
drop_na(if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved) %>%
filter(if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved != "NA - Injury not sustained during sexual intercourse") %>%
mutate(if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved = factor(if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
levels = c(
"Patient on top (Missionary/face to face)",
"Partner on top of patient",
"Partner on top of patient and facing away (Reverse cowgirl/cowboy)",
"Patient behind partner (Doggy style)",
"Side to side (spooning)",
"Other"
))) %>%
tabyl(if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved) %>%
mutate(
"Position" = if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Position",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Position | n | Percent |
|---|---|---|
| Patient on top (Missionary/face to face) | 17 | 30 |
| Partner on top of patient | 13 | 23 |
| Partner on top of patient and facing away (Reverse cowgirl/cowboy) | 3 | 5 |
| Patient behind partner (Doggy style) | 21 | 38 |
| Side to side (spooning) | 1 | 2 |
| Other | 1 | 2 |
predictors %>%
drop_na(was_pain_present_at_presentation) %>%
tabyl(was_pain_present_at_presentation) %>%
mutate(
"Pain at Presentation" = was_pain_present_at_presentation,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Pain at Presentation",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Pain at Presentation | n | Percent |
|---|---|---|
| No | 35 | 15 |
| Yes | 191 | 85 |
predictors %>%
drop_na(was_there_immediate_detumescence_loss_of_erection) %>%
tabyl(was_there_immediate_detumescence_loss_of_erection) %>%
mutate(
"Detumescence" = was_there_immediate_detumescence_loss_of_erection,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Detumescence",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Detumescence | n | Percent |
|---|---|---|
| Yes | 179 | 88 |
| No | 25 | 12 |
predictors %>%
drop_na(was_an_audible_pop_reported_by_the_patient) %>%
tabyl(was_an_audible_pop_reported_by_the_patient) %>%
mutate(
"Audible Pop" = was_an_audible_pop_reported_by_the_patient,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Audible Pop",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Audible Pop | n | Percent |
|---|---|---|
| No | 61 | 32 |
| Yes | 130 | 68 |
Composite variable based on ‘was_penile_bruising_present’ and
‘did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary’
bruise_summary <- predictors %>%
drop_na(was_penile_bruising_present) %>%
mutate(
scrotum = case_when(
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary %in% c(
"Scrotum",
"Scrotum - Lower abdomen",
"Scrotum - Lower abdomen - Perineum",
"Scrotum - Not clear from information available",
"Scrotum - Perineum",
"Scrotum - Lower abdomen - Perineum - No bruising present - Not clear from information available"
) ~ "Yes",
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary == "No bruising present" |
was_penile_bruising_present == "No" ~ "No",
TRUE ~ NA_character_
),
lower_abdomen = case_when(
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary %in% c(
"Lower abdomen",
"Scrotum - Lower abdomen",
"Scrotum - Lower abdomen - Perineum",
"Scrotum - Lower abdomen - Perineum - No bruising present - Not clear from information available"
) ~ "Yes",
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary == "No bruising present" |
was_penile_bruising_present == "No" ~ "No",
TRUE ~ NA_character_
),
perineum = case_when(
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary %in% c(
"Perineum",
"Scrotum - Lower abdomen - Perineum",
"Scrotum - Perineum",
"Scrotum - Lower abdomen - Perineum - No bruising present - Not clear from information available"
) ~ "Yes",
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary == "No bruising present" |
was_penile_bruising_present == "No" ~ "No",
TRUE ~ NA_character_
),
no_bruising = case_when(
scrotum == "No" & lower_abdomen == "No" & perineum == "No" ~ "Yes",
scrotum == "Yes" | lower_abdomen == "Yes" | perineum == "Yes" ~ "No",
TRUE ~ NA_character_
)
) %>%
select(scrotum, lower_abdomen, perineum, no_bruising) %>%
pivot_longer(cols = everything(), names_to = "Location", values_to = "Value") %>%
group_by(Location, Value) %>%
summarise(n = n(), .groups = "drop") %>%
group_by(Location) %>%
mutate(pct = 100 * n / sum(n)) %>%
ungroup() %>%
mutate(display = paste0(n, " (", sprintf("%.1f", pct), "%)")) %>%
select(Location, Value, display) %>%
pivot_wider(names_from = Value, values_from = display)
bruise_summary %>%
kable(
caption = "Counts and Percentages of Bruising by Location",
align = c("l", "c", "c", "c"),
col.names = c("Location", "Yes", "No", "Missing")
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2") %>%
column_spec(1, bold = TRUE)
| Location | Yes | No | Missing |
|---|---|---|---|
| lower_abdomen | 106 (42.7%) | 21 (8.5%) | 121 (48.8%) |
| no_bruising | 89 (35.9%) | 106 (42.7%) | 53 (21.4%) |
| perineum | 106 (42.7%) | 8 (3.2%) | 134 (54.0%) |
| scrotum | 106 (42.7%) | 79 (31.9%) | 63 (25.4%) |
predictors %>%
drop_na(what_incision_was_made) %>%
tabyl(what_incision_was_made) %>%
mutate(
"Incision" = what_incision_was_made,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Incision",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Incision | n | Percent |
|---|---|---|
| longitudinal | 59 | 24 |
| Penoscrotal | 96 | 38 |
| Subcoronal with degloving of penis | 81 | 32 |
| Subcoronal without degloving of penis | 7 | 3 |
| Other | 8 | 3 |
predictors %>%
drop_na(was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
tabyl(was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
mutate(
"Transfer for Repair" = was_the_patient_transferred_from_another_hospital_for_surgical_repair,
Percent = round(percent * 100),
.keep = "unused") %>%
select(c("Transfer for Repair",
n,
Percent)) %>%
gt() %>%
gt_theme_espn()
| Transfer for Repair | n | Percent |
|---|---|---|
| No | 198 | 77 |
| Yes | 58 | 23 |
predictors <- predictors %>% mutate(
presentation_to_knife_to_skin = difftime(
what_time_did_surgical_repair_take_place_knife_to_skin,
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional,
units = "mins"
) %>% as.numeric()
)
presentation_to_knife_to_skin_plot <- ggplot(predictors, aes(x = presentation_to_knife_to_skin / 60)) +
geom_histogram(bins = 50, fill = "skyblue", color = "black") +
labs(
title = "Histogram of Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) + xlim(0,50) +
theme_minimal()
presentation_to_knife_to_skin_plot
## Warning: Removed 56 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_bar()`).
time_from_injury_to_th <- predictors %>%
mutate(
time_from_injury_to_th = difftime(what_time_did_surgical_repair_take_place_knife_to_skin,
what_was_the_estimated_date_and_time_of_injury,
units = "mins")
) %>%
mutate(
time_from_injury_to_th = ifelse(time_from_injury_to_th < 0 | time_from_injury_to_th > (140*60),
NA,
time_from_injury_to_th)
)
time_from_injury_to_th$time_from_injury_to_th <- as.numeric(time_from_injury_to_th$time_from_injury_to_th)
ggplot(time_from_injury_to_th, aes(x = time_from_injury_to_th / 60)) +
geom_histogram(bins = 50, fill = "skyblue", color = "black") +
labs(
title = "Histogram of Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal()
## Warning: Removed 41 rows containing non-finite outside the scale range
## (`stat_bin()`).
time_from_injury_to_th <- time_from_injury_to_th %>%
mutate(
time_from_injury_to_th1 = time_from_injury_to_th / 60,
presentation_to_knife_to_skin1 = presentation_to_knife_to_skin / 60,
time_from_injury_to_th_bins = cut(
time_from_injury_to_th1,
breaks = c(-Inf, 6, 12, 24, 36, Inf),
labels = c("<6h", "6–12h", "12–24h", "24-36h", ">36h")
),
presentation_to_knife_to_skin_bins = cut(
presentation_to_knife_to_skin1,
breaks = c(-Inf, 6, 12, 24, 36, Inf),
labels = c("<6h", "6–12h", "12–24h", "24-36h", ">36h")
)
)
p1 <- time_from_injury_to_th %>%
drop_na(time_from_injury_to_th_bins) %>%
ggplot(aes(x = time_from_injury_to_th_bins)) +
geom_bar(fill = "#2C7BB6", colour = "black") +
labs(
x = "Time from Injury to Theatre (hours, binned)",
y = "Count"
) + ylim(0,100) +
theme_minimal()
p2 <- time_from_injury_to_th %>%
drop_na(presentation_to_knife_to_skin_bins) %>%
ggplot(aes(x = presentation_to_knife_to_skin_bins)) +
geom_bar(fill = "#D7191C", colour = "black") +
labs(
x = "Presentation to Knife-to-Skin (hours, binned)",
y = "Count"
) + ylim(0,100) +
theme_minimal()
time_binned_plot <- plot_grid(p1, p2, labels = c("A", "B"))
time_binned_plot
predictors <- predictors %>%
mutate(
was_imaging_performed_if_so_what_imaging_select_all_that_apply = recode_factor(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
"No" = "No",
"Yes - Both Ultrasound and MRI - Not clear from information available" = NA_character_,
"Yes - Both Ultrasound and MRI" = "MRI & US",
"Yes - MRI penis" = "MRI",
"Yes - MRI penis - Yes - Ultrasound" = "MRI & US",
"Yes - Ultrasound" = "US"
),
did_the_reporting_radiologist_have_a_specialist_interest_in_urology = recode_factor(did_the_reporting_radiologist_have_a_specialist_interest_in_urology,
"No" = "No",
"Yes" = "Yes",
"Not clear from information available" = NA_character_
),
was_the_patient_transferred_between_hospitals_for_specialist_imaging = recode_factor(was_the_patient_transferred_between_hospitals_for_specialist_imaging,
"No" = "No",
"Yes" = "Yes",
"Not clear from information available" = NA_character_
)
)
tab <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
mutate(any_imaging = ifelse(was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No",
"No",
"Yes") %>% as.factor()) %>%
tabyl(
any_imaging,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology
) %>%
adorn_totals("row") %>%
adorn_totals("col") %>%
adorn_percentages("row")
# Get counts separately
tab_counts <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
tabyl(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
adorn_totals("row") %>%
adorn_totals("col")
# Combine counts and percentages into n (%)
tab_n_pct <- tab_counts
for(col in 2:ncol(tab_counts)) {
tab_n_pct[[col]] <- paste0(tab_counts[[col]], " (",
round(tab[[col]]*100, 1), "%)")
}
tab_n_pct %>%
kable("html", escape = FALSE,
col.names = c("Imaging Type", "Not Reported by Subspecialist Radiologist", "Reported by Subspecialist Radiologist", "Total")) %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE, background = "#D3D3D3")
| Imaging Type | Not Reported by Subspecialist Radiologist | Reported by Subspecialist Radiologist | Total |
|---|---|---|---|
| No | 52 (98.1%) | 1 (1.9%) | 53 (100%) |
| MRI & US | 0 (14%) | 10 (86%) | 10 (100%) |
| MRI | 11 (39.7%) | 36 (60.3%) | 47 (100%) |
| US | 6 (98.1%) | 58 (1.9%) | 64 (100%) |
| Total | 69 (14%) | 105 (86%) | 174 (100%) |
tab <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
tabyl(
was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology
) %>%
adorn_totals("row") %>%
adorn_totals("col") %>%
adorn_percentages("row")
# Get counts separately
tab_counts <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
tabyl(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
did_the_reporting_radiologist_have_a_specialist_interest_in_urology) %>%
adorn_totals("row") %>%
adorn_totals("col")
# Combine counts and percentages into n (%)
tab_n_pct <- tab_counts
for(col in 2:ncol(tab_counts)) {
tab_n_pct[[col]] <- paste0(tab_counts[[col]], " (",
round(tab[[col]]*100, 1), "%)")
}
tab_n_pct %>%
kable("html", escape = FALSE,
col.names = c("Imaging Type", "Not Reported by Subspecialist Radiologist", "Reported by Subspecialist Radiologist", "Total")) %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE, background = "#D3D3D3")
| Imaging Type | Not Reported by Subspecialist Radiologist | Reported by Subspecialist Radiologist | Total |
|---|---|---|---|
| No | 52 (98.1%) | 1 (1.9%) | 53 (100%) |
| MRI & US | 0 (0%) | 10 (100%) | 10 (100%) |
| MRI | 11 (23.4%) | 36 (76.6%) | 47 (100%) |
| US | 6 (9.4%) | 58 (90.6%) | 64 (100%) |
| Total | 69 (39.7%) | 105 (60.3%) | 174 (100%) |
predictors <- predictors %>%
mutate(
any_imaging = ifelse(was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No",
"No",
"Yes") %>% as.factor(),
.keep = "all"
)
tab <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
mutate(any_imaging = ifelse(was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No",
"No",
"Yes") %>% as.factor()) %>%
tabyl(
any_imaging,
was_the_patient_transferred_between_hospitals_for_specialist_imaging
) %>%
adorn_totals("row") %>%
adorn_totals("col") %>%
adorn_percentages("row")
# Get counts separately
tab_counts <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
tabyl(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
adorn_totals("row") %>%
adorn_totals("col")
# Combine counts and percentages into n (%)
tab_n_pct <- tab_counts
for(col in 2:ncol(tab_counts)) {
tab_n_pct[[col]] <- paste0(tab_counts[[col]], " (",
round(tab[[col]]*100, 1), "%)")
}
tab_n_pct %>%
kable("html", escape = FALSE,
col.names = c("Imaging Type", "No Transfer", "Transfer", "Total")) %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE, background = "#D3D3D3")
| Imaging Type | No Transfer | Transfer | Total |
|---|---|---|---|
| No | 95 (100%) | 0 (0%) | 95 (100%) |
| MRI & US | 13 (95.4%) | 0 (4.6%) | 13 (100%) |
| MRI | 55 (97.2%) | 5 (2.8%) | 60 (100%) |
| US | 77 (100%) | 2 (0%) | 79 (100%) |
| Total | 240 (95.4%) | 7 (4.6%) | 247 (100%) |
tab <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
tabyl(
was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging
) %>%
adorn_totals("row") %>%
adorn_totals("col") %>%
adorn_percentages("row")
# Get counts separately
tab_counts <- predictors %>%
drop_na(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
tabyl(was_imaging_performed_if_so_what_imaging_select_all_that_apply,
was_the_patient_transferred_between_hospitals_for_specialist_imaging) %>%
adorn_totals("row") %>%
adorn_totals("col")
# Combine counts and percentages into n (%)
tab_n_pct <- tab_counts
for(col in 2:ncol(tab_counts)) {
tab_n_pct[[col]] <- paste0(tab_counts[[col]], " (",
round(tab[[col]]*100, 1), "%)")
}
tab_n_pct %>%
kable("html", escape = FALSE,
col.names = c("Imaging Type", "No Transfer", "Transfer", "Total")) %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE, background = "#D3D3D3")
| Imaging Type | No Transfer | Transfer | Total |
|---|---|---|---|
| No | 95 (100%) | 0 (0%) | 95 (100%) |
| MRI & US | 13 (100%) | 0 (0%) | 13 (100%) |
| MRI | 55 (91.7%) | 5 (8.3%) | 60 (100%) |
| US | 77 (97.5%) | 2 (2.5%) | 79 (100%) |
| Total | 240 (97.2%) | 7 (2.8%) | 247 (100%) |
time_from_injury_to_th %>%
mutate(
imaging = case_when(
was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No" ~ "No",
str_detect(was_imaging_performed_if_so_what_imaging_select_all_that_apply, "Yes") ~ "Yes",
TRUE ~ NA_character_
)
) %>%
select(imaging,
presentation_to_knife_to_skin,
was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
drop_na() %>%
group_by(imaging,
was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
summarise(
mean_p2k = mean(presentation_to_knife_to_skin, na.rm = TRUE),
sd_p2k = sd(presentation_to_knife_to_skin, na.rm = TRUE),
.groups = "drop"
) %>%
ggplot(aes(
x = imaging,
y = mean_p2k,
fill = was_the_patient_transferred_from_another_hospital_for_surgical_repair
)) +
geom_col(position = position_dodge())
# geom_errorbar(aes(ymin = mean_p2k - sd_p2k, ymax = mean_p2k + sd_p2k),
# position = position_dodge(0.9),
# width = 0.2)
I wonder if this is type II statistical error
plot_data <- time_from_injury_to_th %>%
mutate(
imaging = case_when(
was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No" ~ "No",
str_detect(was_imaging_performed_if_so_what_imaging_select_all_that_apply, "Yes") ~ "Yes",
TRUE ~ NA_character_
)
) %>%
select(imaging, was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
drop_na() %>%
count(imaging, was_the_patient_transferred_from_another_hospital_for_surgical_repair) %>%
group_by(imaging) %>%
mutate(pct = n / sum(n) * 100)
chi_test <- chisq.test(
xtabs(n ~ imaging + was_the_patient_transferred_from_another_hospital_for_surgical_repair, data = plot_data)
)
pval_label <- paste0("Chi-square p = ", signif(chi_test$p.value, 3))
# Plot raw counts
p_counts <- ggplot(plot_data, aes(x = imaging, y = n,
fill = was_the_patient_transferred_from_another_hospital_for_surgical_repair)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = n),
position = position_dodge(width = 0.8), vjust = -0.3, size = 4) +
annotate("text", x = 1.5, y = max(plot_data$n) * 1.1, label = pval_label,
size = 5, fontface = "italic") +
scale_fill_brewer(palette = "Set2", name = "Transferred from another hospital") +
labs(title = "Raw Counts", x = "Imaging performed", y = "Number of patients") +
theme_minimal(base_size = 14) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top")
# Plot percentages
p_pct <- ggplot(plot_data, aes(x = imaging, y = pct,
fill = was_the_patient_transferred_from_another_hospital_for_surgical_repair)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = paste0(round(pct, 1), "%")),
position = position_dodge(width = 0.8), vjust = -0.3, size = 4) +
scale_fill_brewer(palette = "Set2", name = "Transferred from another hospital") +
labs(title = "Percentages", x = "Imaging performed", y = "Percentage of patients") +
theme_minimal(base_size = 14) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top")
plot_grid(p_counts, p_pct)
plot_data <- time_from_injury_to_th %>%
mutate(
imaging = case_when(
was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No" ~ "No",
str_detect(was_imaging_performed_if_so_what_imaging_select_all_that_apply, "Yes") ~ "Yes",
TRUE ~ NA_character_
)
) %>%
select(imaging, was_a_concurrent_circumcision_performed) %>%
filter(was_a_concurrent_circumcision_performed != "Patient previously circumcised") %>%
drop_na() %>%
count(imaging, was_a_concurrent_circumcision_performed) %>%
group_by(imaging) %>%
mutate(pct = n / sum(n) * 100)
plot_data$was_a_concurrent_circumcision_performed <- factor(plot_data$was_a_concurrent_circumcision_performed,
levels = c("Yes",
"No"))
chi_test <- chisq.test(
xtabs(n ~ imaging + was_a_concurrent_circumcision_performed, data = plot_data)
)
pval_label <- paste0("Chi-square p = ", signif(chi_test$p.value, 3))
# Plot raw counts
p_counts <- ggplot(plot_data, aes(x = imaging, y = n,
fill = was_a_concurrent_circumcision_performed)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = n),
position = position_dodge(width = 0.8), vjust = -0.3, size = 4) +
annotate("text", x = 1.5, y = max(plot_data$n) * 1.1, label = pval_label,
size = 5, fontface = "italic") +
scale_fill_brewer(palette = "Set2", name = "Circumcision Performed") +
labs(title = "Raw Counts", x = "Imaging performed", y = "Number of patients") +
theme_minimal(base_size = 14) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top")
# Plot percentages
p_pct <- ggplot(plot_data, aes(x = imaging, y = pct,
fill = was_a_concurrent_circumcision_performed)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = paste0(round(pct, 1), "%")),
position = position_dodge(width = 0.8), vjust = -0.3, size = 4) +
scale_fill_brewer(palette = "Set2", name = "Circumcision Performed") +
labs(title = "Percentages", x = "Imaging performed", y = "Percentage of patients") +
theme_minimal(base_size = 14) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top")
plot_grid(p_counts, p_pct)
volume <- snap %>%
select(submission_id,
please_select_the_deanery_hospital_you_are_completing_the_form_for) %>%
group_by(please_select_the_deanery_hospital_you_are_completing_the_form_for) %>%
summarise(n = n())
volume %>%
arrange(desc(n)) %>%
gt() %>% gt_theme_espn()
| please_select_the_deanery_hospital_you_are_completing_the_form_for | n |
|---|---|
| London, North University College Hospital, London | 39 |
| London, South King's College Hospital, London | 10 |
| Yorkshire & Humber St James University Hospital, Leeds | 10 |
| East Midlands Nottingham City Hospital | 8 |
| South West Southmead Hospital, Bristol | 8 |
| North East Freeman Hospital, Newcastle | 7 |
| London, South St George's Hospital, London | 6 |
| Scotland Western General Hospital, Edinburgh | 6 |
| South Central Southampton General Hospital | 6 |
| East Midlands Leicester General Hospital | 5 |
| East of England Norfolk and Norwich University Hospital | 5 |
| London, South Guy's and Thomas's Hospital | 5 |
| South Central Queen Alexandra Hospital, Portsmouth | 5 |
| South West Cheltenham General Hospital | 5 |
| South West Royal Devon & Exeter Hospital | 5 |
| East Midlands Royal Derby Hospital | 4 |
| Kent, Surrey, Sussex Princess Royal Hospital, Hayward's Heath | 4 |
| London, North Northwick Park Hospital | 4 |
| North East Sunderland Royal Hospital | 4 |
| North West Cumberland Infirmary, Carlisle | 4 |
| Yorkshire & Humber Castle Hill Hospital, Hull | 4 |
| Kent, Surrey, Sussex Frimley Park Hospital | 3 |
| London, North Barking, Havering & Redbridge University Hospital | 3 |
| London, North West Middlesex University Hospital | 3 |
| London, North Whipps Cross Hospital, London | 3 |
| North West Arrowe Parke Hospital, Wirral | 3 |
| North West Blackpool Victoria Hospital | 3 |
| North West Royal Liverpool & Broadgreen University Hospitals | 3 |
| North West Stepping Hill Hospital, Stockport | 3 |
| North West Whiston Hospital | 3 |
| South Central Royal Berkshire Hospital | 3 |
| South West Derriford Hospital, Plymouth | 3 |
| South West Royal Cornwall Hospital, Truro | 3 |
| South West The Great Western Hospital, Swindon | 3 |
| Wales University Hospital of Wales, Cardiff | 3 |
| West Midlands Royal Stoke University Hospitals | 3 |
| West Midlands Sandwell District General Hospital, West Bromwich | 3 |
| Yorkshire & Humber Bradford Royal Infirmary | 3 |
| Yorkshire & Humber Pinderfields General Hospital, Wakefield | 3 |
| East of England Ipswich Hospital, Suffolk | 2 |
| East of England Southend Hospital | 2 |
| Kent, Surrey, Sussex Kent & Canterbury Hospital | 2 |
| Kent, Surrey, Sussex Medway Maritime Hospital, Gillingham | 2 |
| North East The James Cook University Hospital, Middlesborough | 2 |
| North West Manchester Royal Infirmary | 2 |
| North West North Manchester General Hospital | 2 |
| North West Royal Blackburn Hospital | 2 |
| North West Royal Bolton Hospital | 2 |
| North West Warrington District General Hospital | 2 |
| Scotland Glasgow Royal Infirmary | 2 |
| South West Musgrove Park Hospital, Taunton | 2 |
| Wales Royal Gwent Hospital | 2 |
| West Midlands Alexandra Hospital, Redditch | 2 |
| West Midlands University Hospital, Coventry | 2 |
| East Midlands Chesterfield Royal Hospital | 1 |
| East Midlands Kettering General Hospital | 1 |
| East Midlands Lincoln County Hospital | 1 |
| East Midlands Northampton General Hospital | 1 |
| East of England Addenbrooke's Hospital, Cambridge | 1 |
| East of England Peterborough City Hospital | 1 |
| East of England Queen Elizabeth Hospital, King's Lynn | 1 |
| Kent, Surrey, Sussex Eastbourne District General Hospital | 1 |
| London, North Chelsea & Westminster Hospital, London | 1 |
| London, North Hillingdon Hospital, Uxbridge | 1 |
| North East Bishop Auckland Hospital | 1 |
| Scotland Aberdeen Royal Infirmary | 1 |
| Scotland Queen Elizabeth University Hospital, Glasgow | 1 |
| South West Royal United Hospital, Bath | 1 |
| Wales Morriston Hospital, Swansea | 1 |
| West Midlands Hereford County Hospital | 1 |
| West Midlands Queen's Hospital, Burton-on-Trent | 1 |
| Yorkshire & Humber Airedale Hospital | 1 |
| Yorkshire & Humber Royal Hallamshire Hospital, Sheffield | 1 |
| Yorkshire & Humber Scunthorpe General Hospital | 1 |
UCLH seems to be an outlier in terms of volume - this should be
“High”
Then arbitrarily subdivide into “Medium” (>5) and “Low”
(</=5)
volume <- volume %>%
ungroup() %>%
mutate(
volume = case_when(
n > 30 ~ "High",
n > 5 & n <= 30 ~ "Medium",
n < 6 ~ "Low"
),
volume_n = n
)
volume$volume <- factor(volume$volume,
levels = c("High",
"Medium",
"Low"))
volume_clean <- volume %>%
mutate(hospital_clean = str_squish(str_replace_all(
please_select_the_deanery_hospital_you_are_completing_the_form_for, "[\r\n]", " "
)))
predictors <- predictors %>%
mutate(hospital_clean = str_squish(str_replace_all(
please_select_the_deanery_hospital_you_are_completing_the_form_for, "[\r\n]", " "
))) %>%
left_join(
volume_clean %>% select(hospital_clean, volume, volume_n),
by = "hospital_clean"
)
# Amended to be continuous variable
# mutate(hospital_clean = str_squish(str_replace_all(
# please_select_the_deanery_hospital_you_are_completing_the_form_for, "[\r\n]", " "
# ))) %>%
# mutate(
# volume = case_when(
# hospital_clean %in% (volume_clean %>% filter(volume == "High") %>% pull(hospital_clean)) ~ "High",
# hospital_clean %in% (volume_clean %>% filter(volume == "Medium") %>% pull(hospital_clean)) ~ #"Medium",
# hospital_clean %in% (volume_clean %>% filter(volume == "Low") %>% pull(hospital_clean)) ~ "Low",
# TRUE ~ NA_character_
# )
# )
volume %>%
select(volume) %>%
group_by(volume) %>%
summarise("Number of Units" = n()) %>%
gt() %>%
gt_theme_espn()
| volume | Number of Units |
|---|---|
| High | 1 |
| Medium | 8 |
| Low | 65 |
injury_location <- snap %>%
subset(select = c(locality,
laterality,
where_was_the_site_of_the_fracture_answer_all_that_apply))
predictors <- predictors %>% mutate(
n_locations = sum(c(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Distal"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Mid"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Proximal"),
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Crura")
)),
proximal = case_when(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Proximal") ~ "Yes",
TRUE ~ "No"
),
mid = case_when(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Mid") ~ "Yes",
TRUE ~ "No"
),
distal = case_when(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Distal") ~ "Yes",
TRUE ~ "No"
),
crura = case_when(
str_detect(where_was_the_site_of_the_fracture_answer_all_that_apply, "Crura") ~ "Yes",
TRUE ~ "No"
),
multi_level = case_when(
n_locations > 1 ~ "Yes",
TRUE ~ "No"
),
imaging = case_when(
was_imaging_performed_if_so_what_imaging_select_all_that_apply == "No" ~ "No",
was_imaging_performed_if_so_what_imaging_select_all_that_apply %in% c("MRI & US",
"MRI",
"US") ~ "Yes",
TRUE ~ "No"
),
.keep = "all"
) %>% select(-n_locations) %>% cbind()
tab <- predictors %>%
drop_na(locality, laterality) %>%
tabyl(locality, laterality) %>%
adorn_totals("row") %>%
adorn_totals("col") %>%
adorn_percentages("row")
# Get counts separately
tab_counts <- predictors %>%
drop_na(locality, laterality) %>%
tabyl(locality, laterality) %>%
adorn_totals("row") %>%
adorn_totals("col")
# Combine counts and percentages into n (%)
tab_n_pct <- tab_counts
for(col in 2:ncol(tab_counts)) {
tab_n_pct[[col]] <- paste0(tab_counts[[col]], " (",
round(tab[[col]]*100, 1), "%)")
}
tab_n_pct %>%
kable("html", escape = FALSE,
col.names = c("Location", "Bilateral", "Unilateral", "Total")) %>%
kable_styling(full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed")) %>%
row_spec(0, bold = TRUE, background = "#D3D3D3")
| Location | Bilateral | Unilateral | Total |
|---|---|---|---|
| Crura | 0 (0%) | 9 (100%) | 9 (100%) |
| Distal | 1 (4.3%) | 22 (95.7%) | 23 (100%) |
| Mid | 7 (9.5%) | 67 (90.5%) | 74 (100%) |
| Multi-level | 3 (42.9%) | 4 (57.1%) | 7 (100%) |
| Proximal | 14 (12.3%) | 100 (87.7%) | 114 (100%) |
| Total | 25 (11%) | 202 (89%) | 227 (100%) |
predictors_pres_to_th <- predictors %>%
subset(select = -c(what_time_did_surgical_repair_take_place_knife_to_skin,
what_was_the_estimated_date_and_time_of_injury,
when_was_the_patient_first_seen_in_hospital_by_a_healthcare_professional,
submission_date,
please_select_the_deanery_hospital_you_are_completing_the_form_for,
what_suture_was_used_for_the_repair_of_the_tunical_fracture
))
predictors_pres_to_th %>% head() %>% as_tabyl() %>% gt() %>% gt_theme_espn()
| submission_id | what_age_was_the_patient_at_the_time_of_the_injury | mechanism_of_injury | if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved | did_the_patient_have_a_history_of_a_prior_penile_fracture | was_pain_present_at_presentation | was_there_immediate_detumescence_loss_of_erection | was_an_audible_pop_reported_by_the_patient | was_penile_bruising_present | did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary | was_there_a_suspicion_of_urethral_injury_at_presentation | if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply | was_imaging_performed_if_so_what_imaging_select_all_that_apply | was_the_patient_transferred_between_hospitals_for_specialist_imaging | did_the_reporting_radiologist_have_a_specialist_interest_in_urology | did_the_patient_get_to_theatre_within_24_hours_of_injury | did_the_patient_get_to_theatre_within_24_hours_of_presentation | was_the_patient_transferred_from_another_hospital_for_surgical_repair | were_antibiotics_given_at_induction | was_a_consultant_present_in_theatre | was_a_trainee_present_in_theatre | what_was_the_grade_of_the_primary_surgeon | was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology | was_a_urologist_with_a_specialist_interest_in_andrology_present_in_theatre | where_was_the_site_of_the_fracture_answer_all_that_apply | what_incision_was_made | was_a_concurrent_circumcision_performed | were_intraoperative_urethral_investigations_performed_select_all_that_apply | was_a_urethral_injury_noted_at_surgery | if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra | was_follow_up_arranged | presentation_to_knife_to_skin | laterality | locality | type_of_suture | any_imaging | hospital_clean | volume | volume_n | proximal | mid | distal | crura | multi_level | imaging |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 53 | Sexual intercourse trauma | NA | No | No | NA | NA | Yes | NA | No | No clinical suspicion of urethral injury | US | No | NA | No | No | No | Yes | Yes | Yes | Consultant | NA | NA | Distal shaft right corpora | longitudinal | No | Not performed | No | NA | Yes | 527052 | Unilateral | Distal | Non-absorbable | Yes | Wales Morriston Hospital, Swansea | Low | 1 | No | No | Yes | No | No | Yes |
| 2 | 42 | Sexual intercourse trauma | NA | No | Yes | Yes | No | Yes | Scrotum - Lower abdomen | Yes | Blood at urethal meatus | No | No | No | NA | NA | Yes | Yes | Yes | Yes | Specialist Registrar | No | No | Proximal shaft left corpora - Proximal shaft right corpora | Penoscrotal | No | Flexible cystoscopy | Yes | Vicryl Rapide 5-0 Suture | Yes | 115 | Bilateral | Proximal | Non-absorbable | No | London, South St George's Hospital, London | Medium | 6 | Yes | No | No | No | No | No |
| 3 | 44 | Sexual intercourse trauma | NA | No | Yes | Yes | NA | No | No bruising present | Yes | Blood at urethal meatus | MRI | No | NA | NA | NA | Yes | Yes | Yes | Yes | Consultant | Yes | Yes | Proximal shaft left corpora - Proximal shaft right corpora | Penoscrotal | No | Not performed | Yes | Vicryl 5-0 Suture | Yes | 7620 | Bilateral | Proximal | Non-absorbable | Yes | London, South St George's Hospital, London | Medium | 6 | Yes | No | No | No | No | Yes |
| 4 | 35 | Sexual intercourse trauma | NA | No | Yes | Yes | NA | Yes | No bruising present | Yes | Other | MRI | No | Yes | Yes | Yes | No | Yes | Yes | Yes | Consultant | Yes | Yes | Mid shaft right corpora | longitudinal | NA | Flexible cystoscopy | No | NA | Yes | 199 | Unilateral | Mid | Non-absorbable | Yes | East Midlands Leicester General Hospital | Low | 5 | No | Yes | No | No | No | Yes |
| 5 | 17 | NA | NA - Injury not sustained during sexual intercourse | No | Yes | NA | Yes | No | No bruising present | No | No clinical suspicion of urethral injury | No | No | No | No | No | No | Yes | Yes | Yes | Consultant | No | No | NA | Subcoronal with degloving of penis | No | Not performed | No | Other | Yes | 2339 | NA | NA | Absorbable | No | North West Arrowe Parke Hospital, Wirral | Low | 3 | No | No | No | No | No | No |
| 6 | 30 | Sexual intercourse trauma | Patient on top (Missionary/face to face) | No | Yes | Yes | Yes | Yes | Scrotum | No | No clinical suspicion of urethral injury | No | No | NA | NA | NA | No | No | Yes | No | Consultant | NA | No | Proximal shaft right corpora | Penoscrotal | No | Not performed | No | Other | Yes | 650 | Unilateral | Proximal | Unclear | No | Wales Royal Gwent Hospital | Low | 2 | Yes | No | No | No | No | No |
plot_missing(predictors_pres_to_th)
plot_bar(predictors_pres_to_th,
ggtheme = theme_classic(),
nrow = 1,
ncol = 1)
## 1 columns ignored with more than 50 categories.
## hospital_clean: 74 categories
outcomes <- outcomes %>%
mutate(
pain = recode_factor(
at_follow_up_did_the_patient_describe_ongoing_pain,
"No" = "No",
"Yes" = "Yes",
"No Follow up" = NA_character_,
"Not from the information available" = NA_character_
),
ed = recode_factor(
did_the_patient_describe_new_or_worsening_erectile_dysfunction_at_follow_up,
"No" = "No",
"Yes - Manageable with medication" = "Yes",
"Yes - Still bothersome despite medication" = "Yes",
"Yes - Unable to quantify from information available" = "Yes",
"No Follow up" = NA_character_,
"Not clear from the information available" = NA_character_
),
abnormal_curvature = recode_factor(
at_follow_up_did_the_patient_describe_penile_curvature,
"No" = "No",
"Yes - Able to have penetrative intercourse" = "Yes",
"Yes - Not clear if limiting penetrative intercourse" = "Yes",
"No Follow up" = NA_character_,
"Not from the information available" = NA_character_
),
waisting_shortening = recode_factor(
at_follow_up_was_there_evidence_of_penile_wasting_or_shortening,
"No" = "No",
"Yes" = "Yes",
"No Follow up" = NA_character_,
"Not clear from the information available" = NA_character_
),
submission_id = submission_id,
.keep = "unused"
)
plot_missing(outcomes %>% select(-submission_id))
variable_labels <- c(
pain = "Ongoing pain",
ed = "Erectile dysfunction",
abnormal_curvature = "Abnormal curvature",
waisting_shortening = "Waisting/shortening"
)
outcomes_summary <- outcomes %>%
select(-submission_id) %>%
pivot_longer(cols = c(pain, ed, abnormal_curvature, waisting_shortening),
names_to = "variable",
values_to = "value") %>%
group_by(variable) %>%
summarise(
n_total = sum(!is.na(value)),
n_missing = sum(is.na(value)),
n_yes = sum(value == "Yes", na.rm = TRUE),
n_no = sum(value == "No", na.rm = TRUE),
pct_yes = round(100 * n_yes / n_total, 1),
.groups = "drop"
)
outcomes_summary %>%
mutate(variable = variable_labels[variable]) %>%
select(c(variable,
n_total,
n_yes,
pct_yes)) %>%
gt() %>%
gt_theme_espn() %>%
fmt_number(columns = c(pct_yes), decimals = 1) %>%
cols_label(
variable = "Outcome",
n_total = "Total (n, non-missing)",
n_yes = "Yes (n)",
pct_yes = "Yes (%)"
)
| Outcome | Total (n, non-missing) | Yes (n) | Yes (%) |
|---|---|---|---|
| Abnormal curvature | 205 | 40 | 19.5 |
| Erectile dysfunction | 213 | 39 | 18.3 |
| Ongoing pain | 158 | 28 | 17.7 |
| Waisting/shortening | 194 | 17 | 8.8 |
predictors_pres_to_th$laterality <- as.factor(predictors_pres_to_th$laterality)
predictors_pres_to_th$locality <- as.factor(predictors_pres_to_th$locality)
predictors_pres_to_th$proximal <- as.factor(predictors_pres_to_th$proximal)
predictors_pres_to_th$distal <- as.factor(predictors_pres_to_th$distal)
predictors_pres_to_th$mid <- as.factor(predictors_pres_to_th$mid)
predictors_pres_to_th$crura <- as.factor(predictors_pres_to_th$crura)
predictors_pres_to_th$multi_level <- as.factor(predictors_pres_to_th$multi_level)
predictors_pres_to_th$imaging <- as.factor(predictors_pres_to_th$imaging)
pain_for_log_reg <- outcomes %>%
select(pain) %>%
cbind(predictors_pres_to_th) %>%
subset(
select = -c(
locality,
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply,
what_was_the_grade_of_the_primary_surgeon,
were_intraoperative_urethral_investigations_performed_select_all_that_apply,
was_follow_up_arranged,
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra,
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology,
was_a_concurrent_circumcision_performed,
was_a_trainee_present_in_theatre,
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary
)
)
pain_for_log_reg_18 <- pain_for_log_reg %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No"))) %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_18_hours_of_presentation = case_when(
presentation_to_knife_to_skin >18 ~ "No",
presentation_to_knife_to_skin <=18 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
pain_for_log_reg_36 <- pain_for_log_reg %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No"))) %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_36_hours_of_presentation = case_when(
presentation_to_knife_to_skin >36 ~ "No",
presentation_to_knife_to_skin <=36 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
pain_for_log_reg_48 <- pain_for_log_reg %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No"))) %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_48_hours_of_presentation = case_when(
presentation_to_knife_to_skin >48 ~ "No",
presentation_to_knife_to_skin <=48 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
plot_missing(pain_for_log_reg)
glue("Number with complete data: {nrow(pain_for_log_reg %>% drop_na())}")
## Number with complete data: 55
ed_for_log_reg <- outcomes %>%
select(ed) %>%
mutate(ed = case_when(ed == "No follow up" ~ NA,
TRUE ~ ed) %>% factor(levels = c("Yes",
"No")),
.keep = "unused") %>%
cbind(predictors_pres_to_th) %>%
subset(select = -c(
locality,
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply,
what_was_the_grade_of_the_primary_surgeon,
were_intraoperative_urethral_investigations_performed_select_all_that_apply,
was_follow_up_arranged,
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra,
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology,
was_a_concurrent_circumcision_performed,
was_a_trainee_present_in_theatre,
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary
))
ed_for_log_reg_18 <- ed_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_18_hours_of_presentation = case_when(
presentation_to_knife_to_skin >18 ~ "No",
presentation_to_knife_to_skin <=18 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
ed_for_log_reg_36 <- ed_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_36_hours_of_presentation = case_when(
presentation_to_knife_to_skin >36 ~ "No",
presentation_to_knife_to_skin <=36 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
ed_for_log_reg_48 <- ed_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_48_hours_of_presentation = case_when(
presentation_to_knife_to_skin >48 ~ "No",
presentation_to_knife_to_skin <=48 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
plot_missing(ed_for_log_reg)
glue("Number with complete data: {nrow(ed_for_log_reg %>% drop_na())}")
## Number with complete data: 52
waisting_shortening_for_log_reg <- outcomes %>%
select(waisting_shortening) %>%
mutate(waisting_shortening = case_when(waisting_shortening == "No follow up" ~ NA,
TRUE ~ waisting_shortening) %>% factor(levels = c("Yes",
"No")),
.keep = "unused") %>%
cbind(predictors_pres_to_th) %>%
subset(select = -c(
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply,
what_was_the_grade_of_the_primary_surgeon,
were_intraoperative_urethral_investigations_performed_select_all_that_apply,
was_follow_up_arranged,
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra,
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology,
was_a_concurrent_circumcision_performed,
was_a_trainee_present_in_theatre,
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary
))
waisting_shortening_for_log_reg_18 <- waisting_shortening_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_18_hours_of_presentation = case_when(
presentation_to_knife_to_skin >18 ~ "No",
presentation_to_knife_to_skin <=18 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
waisting_shortening_for_log_reg_36 <- waisting_shortening_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_36_hours_of_presentation = case_when(
presentation_to_knife_to_skin >36 ~ "No",
presentation_to_knife_to_skin <=36 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
waisting_shortening_for_log_reg_48 <- waisting_shortening_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_48_hours_of_presentation = case_when(
presentation_to_knife_to_skin >48 ~ "No",
presentation_to_knife_to_skin <=48 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
plot_missing(waisting_shortening_for_log_reg)
glue("Number with complete data: {nrow(waisting_shortening_for_log_reg %>% drop_na())}")
## Number with complete data: 51
abnormal_curvature_for_log_reg <- outcomes %>%
select(abnormal_curvature) %>%
mutate(abnormal_curvature = case_when(abnormal_curvature == "No follow up" ~ NA,
TRUE ~ abnormal_curvature) %>% factor(levels = c("Yes",
"No")),
.keep = "unused") %>%
cbind(predictors_pres_to_th) %>%
subset(select = -c(
locality,
if_the_injury_was_sustained_during_sexual_intercourse_what_sexual_position_was_involved,
if_there_was_clinical_suspicion_of_a_urethral_injury_why_was_this_select_all_that_apply,
what_was_the_grade_of_the_primary_surgeon,
were_intraoperative_urethral_investigations_performed_select_all_that_apply,
was_follow_up_arranged,
if_there_was_a_urethral_injury_what_suture_was_used_to_repair_the_urethra,
was_a_specialist_opinion_sought_from_a_urologist_with_a_specialist_interest_in_andrology,
was_a_concurrent_circumcision_performed,
was_a_trainee_present_in_theatre,
did_bruising_extend_over_the_scrotum_lower_abdomen_or_perineum_answer_more_than_one_if_necessary
))
abnormal_curvature_for_log_reg_18 <- abnormal_curvature_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_18_hours_of_presentation = case_when(
presentation_to_knife_to_skin >18 ~ "No",
presentation_to_knife_to_skin <=18 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
abnormal_curvature_for_log_reg_36 <- abnormal_curvature_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_36_hours_of_presentation = case_when(
presentation_to_knife_to_skin >36 ~ "No",
presentation_to_knife_to_skin <=36 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
abnormal_curvature_for_log_reg_48 <- abnormal_curvature_for_log_reg %>%
mutate(
presentation_to_knife_to_skin = presentation_to_knife_to_skin / (60),
did_the_patient_get_to_theatre_within_48_hours_of_presentation = case_when(
presentation_to_knife_to_skin >48 ~ "No",
presentation_to_knife_to_skin <=48 ~ "Yes",
TRUE ~ NA_character_
),
.keep = "all"
) %>% select(-c(did_the_patient_get_to_theatre_within_24_hours_of_presentation,
did_the_patient_get_to_theatre_within_24_hours_of_injury))
plot_missing(abnormal_curvature_for_log_reg)
glue("Number with complete data: {nrow(abnormal_curvature_for_log_reg %>% drop_na())}")
## Number with complete data: 50
time_from_injury_to_th1 <- time_from_injury_to_th %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
knife_to_skin <- predictors %>%
select(submission_id,
presentation_to_knife_to_skin) %>%
left_join(outcomes, by = c("submission_id" = "submission_id")) %>%
left_join(time_from_injury_to_th1, by = c("submission_id" = "submission_id"))
p1 <- knife_to_skin %>%
drop_na(presentation_to_knife_to_skin, pain) %>%
ggplot(aes(x = presentation_to_knife_to_skin / 60, fill = pain)) +
geom_histogram(bins = 50) +
labs(
title = "Histogram of Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
pain)
, aes(x = time_from_injury_to_th / 60, fill = pain)) +
geom_histogram(bins = 50) +
labs(
title = "Histogram of Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
## Warning: Removed 20 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_bar()`).
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
pain),
aes(x = presentation_to_knife_to_skin / 60, fill = pain)) +
geom_density() +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) + xlim(0,100) +
theme_minimal()
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
pain)
, aes(x = time_from_injury_to_th / 60, fill = pain)) +
geom_density() +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) + xlim(0,100) +
theme_minimal()
cowplot::plot_grid(p1, p2)
## Warning: Removed 20 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning: Removed 7 rows containing non-finite outside the scale range
## (`stat_density()`).
time_from_injury_to_th1 <- time_from_injury_to_th %>%
subset(select = c(
submission_id,
time_from_injury_to_th_bins,
presentation_to_knife_to_skin_bins
))
knife_to_skin1 <- time_from_injury_to_th1 %>%
left_join(outcomes, by = c("submission_id" = "submission_id"))
p1 <- knife_to_skin1 %>%
drop_na(presentation_to_knife_to_skin_bins) %>%
group_by(presentation_to_knife_to_skin_bins) %>%
summarise(
n_yes = sum(pain == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = presentation_to_knife_to_skin_bins, y = percent_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0(round(percent_yes, 1), "%")),
vjust = -0.5, size = 3.5) +
labs(
title = "Percentage of Patients Reporting Pain",
x = "Time to Theatre from Presentation (Hours, binned)",
y = "Percentage with Pain"
) +
theme_minimal()
p2 <- knife_to_skin1 %>%
drop_na(presentation_to_knife_to_skin_bins) %>%
group_by(presentation_to_knife_to_skin_bins) %>%
summarise(
n_yes = sum(pain == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = presentation_to_knife_to_skin_bins, y = n_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0("n=",round(n_yes, 1))),
vjust = -0.5, size = 3.5) +
labs(
title = "Number of Patients Reporting Pain",
x = "Time to Theatre from Presentation (Hours, binned)",
y = "Number with Pain"
) +
theme_minimal()
p3 <- knife_to_skin1 %>%
drop_na(time_from_injury_to_th_bins) %>%
group_by(time_from_injury_to_th_bins) %>%
summarise(
n_yes = sum(pain == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = time_from_injury_to_th_bins, y = percent_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0(round(percent_yes, 1), "%")),
vjust = -0.5, size = 3.5) +
labs(
title = "Percentage of Patients Reporting Pain",
x = "Time to Theatre from Injury (Hours, binned)",
y = "Percentage with Pain"
) +
theme_minimal()
p4 <- knife_to_skin1 %>%
drop_na(time_from_injury_to_th_bins) %>%
group_by(time_from_injury_to_th_bins) %>%
summarise(
n_yes = sum(pain == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = time_from_injury_to_th_bins, y = n_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0("n=", round(n_yes, 1))),
vjust = -0.5, size = 3.5) +
labs(
title = "Number of Patients Reporting Pain",
x = "Time to Theatre from Injury (Hours, binned)",
y = "Number with Pain"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
cowplot::plot_grid(p3, p4)
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
ed) %>%
subset(ed != "No follow up"),
aes(x = presentation_to_knife_to_skin/60, fill = ed)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
ed) %>%
subset(ed != "No follow up")
, aes(x = time_from_injury_to_th/60, fill = ed)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
cowplot::plot_grid(p1, p2)
## Warning: Removed 19 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_bar()`).
## Warning: Removed 7 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_bar()`).
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
ed) %>% subset(
ed != "No follow up"
),
aes(x = presentation_to_knife_to_skin/60, fill = ed)) +
geom_density() +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
ed) %>% subset(
ed != "No follow up"
)
, aes(x = time_from_injury_to_th/60, fill = ed)) +
geom_density() +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
cowplot::plot_grid(p1, p2)
## Warning: Removed 19 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning: Removed 7 rows containing non-finite outside the scale range
## (`stat_density()`).
time_from_injury_to_th1 <- time_from_injury_to_th %>%
subset(select = c(
submission_id,
time_from_injury_to_th_bins,
presentation_to_knife_to_skin_bins
))
knife_to_skin1 <- time_from_injury_to_th1 %>%
left_join(outcomes, by = c("submission_id" = "submission_id"))
p1 <- knife_to_skin1 %>%
drop_na(presentation_to_knife_to_skin_bins,
ed) %>%
group_by(presentation_to_knife_to_skin_bins) %>%
summarise(
n_yes = sum(ed == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = presentation_to_knife_to_skin_bins, y = percent_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0(round(percent_yes, 1), "%")),
vjust = -0.5, size = 3.5) +
labs(
title = "Percentage of Patients Reporting ED",
x = "Time to Theatre from Presentation (Hours, binned)",
y = "Percentage with ED"
) +
theme_minimal()
p2 <- knife_to_skin1 %>%
drop_na(presentation_to_knife_to_skin_bins,
ed) %>%
group_by(presentation_to_knife_to_skin_bins) %>%
summarise(
n_yes = sum(ed == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = presentation_to_knife_to_skin_bins, y = n_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0("n=",round(n_yes, 1))),
vjust = -0.5, size = 3.5) +
labs(
title = "Number of Patients Reporting ED",
x = "Time to Theatre from Presentation (Hours, binned)",
y = "Number with ED"
) +
theme_minimal()
p3 <- knife_to_skin1 %>%
drop_na(time_from_injury_to_th_bins,
ed) %>%
group_by(time_from_injury_to_th_bins) %>%
summarise(
n_yes = sum(ed == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = time_from_injury_to_th_bins, y = percent_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0(round(percent_yes, 1), "%")),
vjust = -0.5, size = 3.5) +
labs(
title = "Percentage of Patients Reporting ED",
x = "Time to Theatre from Injury (Hours, binned)",
y = "Percentage with ED"
) +
theme_minimal()
p4 <- knife_to_skin1 %>%
drop_na(time_from_injury_to_th_bins,
ed) %>%
group_by(time_from_injury_to_th_bins) %>%
summarise(
n_yes = sum(ed == "Yes", na.rm = TRUE),
n_total = n(),
percent_yes = 100 * n_yes / n_total,
.groups = "drop"
) %>%
ggplot(aes(x = time_from_injury_to_th_bins, y = n_yes)) +
geom_col(fill = "#D7191C") +
geom_text(aes(label = paste0("n=",round(n_yes, 1))),
vjust = -0.5, size = 3.5) +
labs(
title = "Number of Patients Reporting ED",
x = "Time to Theatre from Injury (Hours, binned)",
y = "Number with ED"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
cowplot::plot_grid(p3, p4)
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
waisting_shortening) %>%
subset(waisting_shortening != "No follow up"),
aes(x = presentation_to_knife_to_skin/60, fill = waisting_shortening)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() +xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
waisting_shortening) %>%
subset(waisting_shortening != "No follow up")
, aes(x = time_from_injury_to_th/60, fill = waisting_shortening)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
## Warning: Removed 15 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_bar()`).
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
waisting_shortening) %>% subset(
waisting_shortening != "No follow up"
),
aes(x = presentation_to_knife_to_skin/60, fill = waisting_shortening)) +
geom_density() +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
waisting_shortening) %>% subset(
waisting_shortening != "No follow up"
)
, aes(x = time_from_injury_to_th/60, fill = waisting_shortening)) +
geom_density() +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
## Warning: Removed 15 rows containing non-finite outside the scale range
## (`stat_density()`).
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
abnormal_curvature) %>%
subset(abnormal_curvature != "No follow up"),
aes(x = presentation_to_knife_to_skin/60, fill = abnormal_curvature)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
abnormal_curvature) %>%
subset(abnormal_curvature != "No follow up")
, aes(x = time_from_injury_to_th/60, fill = abnormal_curvature)) +
geom_histogram(bins = 50) +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal()
cowplot::plot_grid(p1, p2)
## Warning: Removed 19 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_bar()`).
p1 <- ggplot(knife_to_skin %>% drop_na(presentation_to_knife_to_skin,
abnormal_curvature) %>% subset(
abnormal_curvature != "No follow up"
),
aes(x = presentation_to_knife_to_skin/60, fill = abnormal_curvature)) +
geom_density() +
labs(
title = "Time from Presentation to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
p2 <- ggplot(knife_to_skin %>% drop_na(time_from_injury_to_th,
abnormal_curvature) %>% subset(
abnormal_curvature != "No follow up"
)
, aes(x = time_from_injury_to_th/60, fill = abnormal_curvature)) +
geom_density() +
labs(
title = "Time from Injury to Theatre",
x = "Hours",
y = "Count"
) +
theme_minimal() + xlim(0,100)
cowplot::plot_grid(p1, p2)
## Warning: Removed 19 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning: Removed 6 rows containing non-finite outside the scale range
## (`stat_density()`).
# Function to calculate power for two proportions and output as a gt table
calculate_power_table <- function(p1, p2, n1, n2, alpha = 0.05, title = "Power Calculation Results") {
# Complementary probabilities
q1 <- 1 - p1
q2 <- 1 - p2
# Combined proportions
k <- n1 / n2
p_bar <- (p1 + k * p2) / (1 + k)
q_bar <- 1 - p_bar
# Standard error terms
se_diff <- sqrt((p1 * q1 / n1) + (p2 * q2 / n2))
se_null <- sqrt(p_bar * q_bar * (1 / n1 + 1 / n2))
# Z-score for significance level (two-sided)
z_alpha <- qnorm(1 - alpha / 2)
# Z-score under the alternative hypothesis
z_alt <- (p2 - p1) / se_diff - z_alpha * (se_null / se_diff)
# Calculate power
power <- pnorm(z_alt)
# Prepare results for table
results <- data.frame(
Parameter = c("Group 1 Proportion (p1)", "Group 2 Proportion (p2)",
"Group 1 Size (n1)", "Group 2 Size (n2)",
"Significance Level (alpha)", "Calculated Power (%)"),
Value = c(p1, p2, n1, n2, alpha, round(power * 100, 1))
)
# Create gt table
power_table <- gt(results) %>%
tab_header(
title = title,
subtitle = "Based on Two Proportion Test"
) %>%
cols_label(
Parameter = "Parameter",
Value = "Value"
) %>%
fmt_number(
columns = "Value",
decimals = 2,
rows = 1:4
)
return(power_table)
}
n1 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & pain == "Yes")) / n1
n2 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & pain == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Pain")
power
| Power Calculation Results for Post-Operative Pain | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.12 |
| Group 2 Proportion (p2) | 0.11 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 1.50 |
knife_to_skin1 <- knife_to_skin %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
pain_for_log_reg <- pain_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No")))
pain_for_log_reg2 <- pain_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 7920,
NA,
presentation_to_knife_to_skin / (60*6)
),
pain = case_when(pain == "Yes" ~ 1,
pain == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
pain,
imaging,
type_of_suture,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_24_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
pain_lr <- logistf(
pain ~ did_the_patient_get_to_theatre_within_24_hours_of_presentation + imaging + volume_n + type_of_suture +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = pain_for_log_reg2
)
pain_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_24_hours_of_presentation = "Theatre within 24 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume",
type_of_suture = "Type of Suture"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(pain_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 24 hours of Presentation | |||
| No | — | — | |
| Yes | 1.70 | 0.51, 6.42 | 0.4 |
| Imaging | |||
| No | — | — | |
| Yes | 1.17 | 0.33, 4.56 | 0.8 |
| Centre Volume | 0.93 | 0.87, 0.98 | 0.002 |
| Type of Suture | |||
| Absorbable | — | — | |
| Non-absorbable | 0.46 | 0.10, 2.84 | 0.4 |
| Unclear | 1.12 | 0.13, 10.6 | >0.9 |
| Age at Time of Injury | 1.04 | 0.99, 1.10 | 0.12 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.69 | 0.40, 6.37 | 0.5 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 6.16 | 1.70, 27.2 | 0.005 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.00 | 0.00, 8.44 | 0.2 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.00 | 0.00, 5.54 | 0.13 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.00 | 0.00, 2.66 | 0.086 |
| Crural location | |||
| No | — | — | |
| Yes | 0.04 | 0.00, 27.6 | 0.3 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 4,446 | 0.41, 904,601,017 | 0.077 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.68 | 0.13, 3.98 | 0.6 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.79 | 0.01, 13.3 | 0.9 |
| Non-sexual blunt force trauma | 4.35 | 0.85, 21.3 | 0.076 |
| Masturbation injury | 5.25 | 0.64, 58.0 | 0.12 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 116 | |||
# Add back in to get 24hr cut-off: presentation_to_knife_to_skin,
# did_the_patient_get_to_theatre_within_24_hours_of_presentation
# time_from_injury_to_th
pain_lr_predict <-
predict(pain_lr, pain_for_log_reg, type = "response")
pain_outcome <- as.factor(ifelse(pain_for_log_reg$pain == "Yes",
1,
0))
pain_lr_roc <-
pROC::roc(pain_outcome, pain_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(pain_lr_roc)
## Area under the curve: 0.8406
ci.auc(pain_lr_roc)
## 95% CI: 0.7538-0.9274 (DeLong)
pain_lr_roc_data <- cbind(sensitivities = pain_lr_roc$sensitivities,
specificities = pain_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(pain_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
pain_lr_predict2 <- as_tibble(pain_lr_predict) %>% cbind(pain_for_log_reg) %>% subset(select = c(
value,
pain,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
pain_lr_predict2$pain <- ifelse(pain_lr_predict2$pain == "Yes", 1, 0)
pain_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(pain_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = pain_lr_predict2,
obs = "pain",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for Pain Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(pain_lr, pain_for_log_reg2, "pain")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.11 |
pseudoR2_logistf <- function(model, data) {
# Extract log-likelihoods
ll_full <- model$loglik["full"]
ll_null <- model$loglik["null"]
# Sample size
n <- nrow(data)
# Cox & Snell R²
R2_CS <- 1 - exp((2 / n) * (ll_null - ll_full))
# Nagelkerke R²
R2_N <- R2_CS / (1 - exp((2 / n) * ll_null))
R2_N <- R2_N %>% as_tibble()
x <- cbind(
"Score" = "Nagelkerke's R^2",
"Nagelkerke's R^2" = round(R2_N$value, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
# Return as a named list
return(
x
)
}
pseudoR2_logistf(pain_lr, pain_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.365 |
n1 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & ed == "Yes")) / n1
n2 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & ed == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Erectile Dysfunction")
power
| Power Calculation Results for Post-Operative Erectile Dysfunction | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.22 |
| Group 2 Proportion (p2) | 0.11 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.00 |
ed_for_log_reg <- ed_for_log_reg %>%
left_join(knife_to_skin1, by = c("submission_id" = "submission_id")) %>%
mutate(ed = ed %>% factor(levels = c("No", "Yes")))
ed_for_log_reg2 <- ed_for_log_reg %>%
drop_na(
ed,
imaging,
type_of_suture,
volume_n,
volume,
did_the_patient_get_to_theatre_within_24_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>%
mutate(
ed = case_when(ed == "Yes" ~ 1,
ed == "No" ~ 0,
TRUE ~ NA_real_),
presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
.keep = "unused"
)
ed_lr <- logistf(
ed ~ did_the_patient_get_to_theatre_within_24_hours_of_presentation + imaging + volume +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = ed_for_log_reg2
)
ed_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_24_hours_of_presentation = "Theatre within 24 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(ed_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 24 hours of Presentation | |||
| No | — | — | |
| Yes | 0.39 | 0.14, 1.03 | 0.056 |
| Imaging | |||
| No | — | — | |
| Yes | 0.93 | 0.28, 3.23 | >0.9 |
| Centre Volume | |||
| High | — | — | |
| Medium | 1.86 | 0.41, 8.78 | 0.4 |
| Low | 1.64 | 0.45, 6.66 | 0.5 |
| Age at Time of Injury | 1.02 | 0.97, 1.07 | 0.5 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 2.14 | 0.63, 7.44 | 0.2 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.53 | 0.46, 5.24 | 0.5 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 13.5 | 0.02, 37,039 | 0.4 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 9.45 | 0.02, 23,178 | 0.5 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 4.33 | 0.01, 10,704 | 0.7 |
| Crural location | |||
| No | — | — | |
| Yes | 2.60 | 0.01, 2,746 | 0.7 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 0.64 | 0.00, 2,184 | >0.9 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 4.27 | 0.78, 47.8 | 0.10 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.61 | 0.00, 12.2 | 0.8 |
| Non-sexual blunt force trauma | 0.34 | 0.03, 1.72 | 0.2 |
| Masturbation injury | 0.21 | 0.00, 2.01 | 0.2 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 112 | |||
# did_the_patient_get_to_theatre_within_24_hours_of_presentation,
ed_lr_predict <-
predict(ed_lr, ed_for_log_reg, type = "response")
ed_outcome <- as.factor(ifelse(ed_for_log_reg$ed == "Yes",
1,
0))
ed_lr_roc <-
pROC::roc(ed_outcome, ed_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(ed_lr_roc)
## Area under the curve: 0.7775
ci.auc(ed_lr_roc)
## 95% CI: 0.6854-0.8695 (DeLong)
ed_lr_roc_data <- cbind(sensitivities = ed_lr_roc$sensitivities,
specificities = ed_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(ed_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
ed_lr_predict2 <- as_tibble(ed_lr_predict) %>% cbind(ed_for_log_reg) %>% subset(select = c(
value,
ed,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
ed_lr_predict2$ed <- ifelse(ed_lr_predict2$ed == "Yes", 1, 0)
ed_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(ed_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = ed_lr_predict2,
obs = "ed",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for ed Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier_score <- brier(ed_lr, ed_for_log_reg2, "ed")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.156 |
pseudoR2_logistf(ed_lr, ed_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.236 |
n1 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & waisting_shortening == "Yes")) / n1
n2 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & waisting_shortening == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative waisting_shortening")
power
| Power Calculation Results for Post-Operative waisting_shortening | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.08 |
| Group 2 Proportion (p2) | 0.07 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 1.70 |
waisting_shortening_for_log_reg <- waisting_shortening_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(waisting_shortening = waisting_shortening %>% factor(levels = c("Yes",
"No")))
waisting_shortening_for_log_reg2 <- waisting_shortening_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
waisting_shortening = case_when(waisting_shortening == "Yes" ~ 1,
waisting_shortening == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
waisting_shortening,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_24_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
locality,
mechanism_of_injury
) %>% drop_na()
waisting_shortening_lr <- logistf(
waisting_shortening ~ did_the_patient_get_to_theatre_within_24_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + locality + laterality + mechanism_of_injury,
data = waisting_shortening_for_log_reg2
)
waisting_shortening_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_24_hours_of_presentation = "Theatre within 24 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre volume_n"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(waisting_shortening_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 24 hours of Presentation | |||
| No | — | — | |
| Yes | 0.57 | 0.15, 2.04 | 0.4 |
| Imaging | |||
| No | — | — | |
| Yes | 0.39 | 0.08, 1.61 | 0.2 |
| Centre volume_n | 1.01 | 0.96, 1.06 | 0.7 |
| Age at Time of Injury | 1.01 | 0.95, 1.07 | 0.8 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.24 | 0.25, 4.98 | 0.8 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 0.92 | 0.18, 4.27 | >0.9 |
| Site of Injury | |||
| Crura | — | — | |
| Distal | 0.45 | 0.01, 107 | 0.7 |
| Mid | 0.81 | 0.02, 173 | >0.9 |
| Multi-level | 0.49 | 0.00, 151 | 0.8 |
| Proximal | 0.81 | 0.02, 169 | >0.9 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.39 | 0.08, 1.90 | 0.2 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.85 | 0.01, 16.1 | >0.9 |
| Non-sexual blunt force trauma | 0.27 | 0.00, 2.63 | 0.3 |
| Masturbation injury | 0.21 | 0.00, 3.42 | 0.3 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 104 | |||
waisting_shortening_lr_predict <-
predict(waisting_shortening_lr, waisting_shortening_for_log_reg, type = "response")
waisting_shortening_outcome <- as.factor(ifelse(waisting_shortening_for_log_reg$waisting_shortening == "Yes",
1,
0))
waisting_shortening_lr_roc <-
pROC::roc(waisting_shortening_outcome, waisting_shortening_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(waisting_shortening_lr_roc)
## Area under the curve: 0.7579
ci.auc(waisting_shortening_lr_roc)
## 95% CI: 0.6293-0.8866 (DeLong)
waisting_shortening_lr_roc_data <- cbind(sensitivities = waisting_shortening_lr_roc$sensitivities,
specificities = waisting_shortening_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(waisting_shortening_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
waisting_shortening_lr_predict2 <- as_tibble(waisting_shortening_lr_predict) %>% cbind(waisting_shortening_for_log_reg) %>% subset(select = c(
value,
waisting_shortening,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
waisting_shortening_lr_predict2$waisting_shortening <- ifelse(waisting_shortening_lr_predict2$waisting_shortening == "Yes", 1, 0)
waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = waisting_shortening_lr_predict2,
obs = "waisting_shortening",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for waisting_shortening Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(waisting_shortening_lr, waisting_shortening_for_log_reg2, "waisting_shortening")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.107 |
pseudoR2_logistf(waisting_shortening_lr, waisting_shortening_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.146 |
n1 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & abnormal_curvature == "Yes")) / n1
n2 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & abnormal_curvature == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative abnormal_curvature")
power
| Power Calculation Results for Post-Operative abnormal_curvature | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.16 |
| Group 2 Proportion (p2) | 0.17 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 4.90 |
Multi-level removed as model failed to separate
abnormal_curvature_for_log_reg <- abnormal_curvature_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(abnormal_curvature = abnormal_curvature %>% factor(levels = c("Yes",
"No")))
abnormal_curvature_for_log_reg2 <- abnormal_curvature_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
abnormal_curvature = case_when(abnormal_curvature == "Yes" ~ 1,
abnormal_curvature == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
abnormal_curvature,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_24_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
abnormal_curvature_lr <- logistf(
abnormal_curvature ~ did_the_patient_get_to_theatre_within_24_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + laterality + mechanism_of_injury,
data = abnormal_curvature_for_log_reg2
)
abnormal_curvature_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_24_hours_of_presentation = "Theatre within 24 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre volume_n"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(abnormal_curvature_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 24 hours of Presentation | |||
| No | — | — | |
| Yes | 0.62 | 0.21, 1.71 | 0.4 |
| Imaging | |||
| No | — | — | |
| Yes | 0.26 | 0.07, 0.85 | 0.025 |
| Centre volume_n | 1.03 | 0.99, 1.07 | 0.2 |
| Age at Time of Injury | 0.97 | 0.93, 1.02 | 0.3 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.79 | 0.57, 5.64 | 0.3 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 2.49 | 0.79, 8.18 | 0.12 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.35 | 0.00, 5.19 | 0.5 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.40 | 0.00, 6.88 | 0.6 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.22 | 0.00, 3.27 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 0.10 | 0.00, 10.0 | 0.3 |
| laterality | |||
| Bilateral | — | — | |
| Unilateral | 0.54 | 0.14, 2.05 | 0.4 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.57 | 0.00, 9.04 | 0.7 |
| Non-sexual blunt force trauma | 0.38 | 0.07, 1.70 | 0.2 |
| Masturbation injury | 0.10 | 0.00, 1.16 | 0.069 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 109 | |||
abnormal_curvature_lr_predict <-
predict(abnormal_curvature_lr, abnormal_curvature_for_log_reg, type = "response")
abnormal_curvature_outcome <- as.factor(ifelse(abnormal_curvature_for_log_reg$abnormal_curvature == "Yes",
1,
0))
abnormal_curvature_lr_roc <-
pROC::roc(abnormal_curvature_outcome, abnormal_curvature_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(abnormal_curvature_lr_roc)
## Area under the curve: 0.7963
ci.auc(abnormal_curvature_lr_roc)
## 95% CI: 0.7081-0.8845 (DeLong)
abnormal_curvature_lr_roc_data <- cbind(sensitivities = abnormal_curvature_lr_roc$sensitivities,
specificities = abnormal_curvature_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(abnormal_curvature_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
abnormal_curvature_lr_predict2 <- as_tibble(abnormal_curvature_lr_predict) %>% cbind(abnormal_curvature_for_log_reg) %>% subset(select = c(
value,
abnormal_curvature,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
abnormal_curvature_lr_predict2$abnormal_curvature <- ifelse(abnormal_curvature_lr_predict2$abnormal_curvature == "Yes", 1, 0)
abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = abnormal_curvature_lr_predict2,
obs = "abnormal_curvature",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for abnormal_curvature Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(abnormal_curvature_lr, abnormal_curvature_for_log_reg2, "abnormal_curvature")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.165 |
pseudoR2_logistf(abnormal_curvature_lr, abnormal_curvature_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.297 |
n1 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & pain == "Yes")) / n1
n2 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(pain_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & pain == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Pain")
power
| Power Calculation Results for Post-Operative Pain | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.12 |
| Group 2 Proportion (p2) | 0.11 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 1.50 |
knife_to_skin1 <- knife_to_skin %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
pain_for_log_reg <- pain_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No")))
pain_for_log_reg2 <- pain_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 7920,
NA,
presentation_to_knife_to_skin / (60*6)
),
pain = case_when(pain == "Yes" ~ 1,
pain == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
pain,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
pain_lr <- logistf(
pain ~ presentation_to_knife_to_skin + imaging +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery + volume_n +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = pain_for_log_reg2
)
pain_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
presentation_to_knife_to_skin = "Time from Presentation to Theatre (6 Hour Blocks)",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(pain_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Time from Presentation to Theatre (6 Hour Blocks) | 0.88 | 0.70, 1.01 | 0.081 |
| Imaging | |||
| No | — | — | |
| Yes | 1.28 | 0.39, 4.46 | 0.7 |
| Age at Time of Injury | 1.04 | 0.99, 1.10 | 0.14 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 0.86 | 0.18, 3.23 | 0.8 |
| Centre Volume | 0.93 | 0.88, 0.98 | 0.003 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 5.32 | 1.57, 20.1 | 0.007 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.02 | 0.00, 94.5 | 0.4 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 31.1 | 0.3 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 23.4 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 0.21 | 0.00, 106 | 0.6 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 408 | 0.04, 12,423,766 | 0.2 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.44 | 0.09, 2.18 | 0.3 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.74 | 0.00, 12.8 | 0.9 |
| Non-sexual blunt force trauma | 4.60 | 0.88, 23.4 | 0.069 |
| Masturbation injury | 8.83 | 1.07, 90.3 | 0.044 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 125 | |||
# Add back in to get 24hr cut-off: presentation_to_knife_to_skin,
# did_the_patient_get_to_theatre_within_24_hours_of_presentation
# time_from_injury_to_th
pain_lr_predict <-
predict(pain_lr, pain_for_log_reg, type = "response")
pain_outcome <- as.factor(ifelse(pain_for_log_reg$pain == "Yes",
1,
0))
pain_lr_roc <-
pROC::roc(pain_outcome, pain_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(pain_lr_roc)
## Area under the curve: 0.5595
ci.auc(pain_lr_roc)
## 95% CI: 0.4365-0.6824 (DeLong)
pain_lr_roc_data <- cbind(sensitivities = pain_lr_roc$sensitivities,
specificities = pain_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(pain_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
pain_lr_predict2 <- as_tibble(pain_lr_predict) %>% cbind(pain_for_log_reg) %>% subset(select = c(
value,
pain,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
pain_lr_predict2$pain <- ifelse(pain_lr_predict2$pain == "Yes", 1, 0)
pain_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(pain_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = pain_lr_predict2,
obs = "pain",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for Pain Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(pain_lr, pain_for_log_reg2, "pain")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.106 |
pseudoR2_logistf <- function(model, data) {
# Extract log-likelihoods
ll_full <- model$loglik["full"]
ll_null <- model$loglik["null"]
# Sample size
n <- nrow(data)
# Cox & Snell R²
R2_CS <- 1 - exp((2 / n) * (ll_null - ll_full))
# Nagelkerke R²
R2_N <- R2_CS / (1 - exp((2 / n) * ll_null))
R2_N <- R2_N %>% as_tibble()
x <- cbind(
"Score" = "Nagelkerke's R^2",
"Nagelkerke's R^2" = round(R2_N$value, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
# Return as a named list
return(
x
)
}
pseudoR2_logistf(pain_lr, pain_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.334 |
n1 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & ed == "Yes")) / n1
n2 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(ed_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & ed == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Erectile Dysfunction")
power
| Power Calculation Results for Post-Operative Erectile Dysfunction | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.22 |
| Group 2 Proportion (p2) | 0.11 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.00 |
ed_for_log_reg <- ed_for_log_reg %>%
left_join(knife_to_skin1, by = c("submission_id" = "submission_id")) %>%
mutate(ed = ed %>% factor(levels = c("No", "Yes")))
ed_for_log_reg2 <- ed_for_log_reg %>%
drop_na(
ed,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>%
mutate(
ed = case_when(ed == "Yes" ~ 1,
ed == "No" ~ 0,
TRUE ~ NA_real_),
presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
.keep = "unused"
)
ed_lr <- logistf(
ed ~ presentation_to_knife_to_skin + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = ed_for_log_reg2
)
ed_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
presentation_to_knife_to_skin = "Time from Presentation to Theatre (6 Hour blocks)",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(ed_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Time from Presentation to Theatre (6 Hour blocks) | 1.16 | 0.97, 1.40 | 0.10 |
| Imaging | |||
| No | — | — | |
| Yes | 0.80 | 0.24, 2.68 | 0.7 |
| Centre Volume | 0.99 | 0.95, 1.03 | 0.6 |
| Age at Time of Injury | 1.02 | 0.97, 1.07 | 0.5 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 3.18 | 0.94, 11.4 | 0.063 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.41 | 0.42, 4.77 | 0.6 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 11.7 | 0.01, 38,661 | 0.5 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 15.5 | 0.03, 40,330 | 0.4 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 6.13 | 0.01, 16,138 | 0.6 |
| Crural location | |||
| No | — | — | |
| Yes | 6.42 | 0.02, 7,159 | 0.5 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 0.20 | 0.00, 560 | 0.7 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 7.38 | 1.32, 86.9 | 0.020 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.42 | 0.00, 10.2 | 0.6 |
| Non-sexual blunt force trauma | 0.34 | 0.03, 1.71 | 0.2 |
| Masturbation injury | 0.37 | 0.00, 4.11 | 0.5 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 136 | |||
# did_the_patient_get_to_theatre_within_24_hours_of_presentation,
ed_lr_predict <-
predict(ed_lr, ed_for_log_reg, type = "response")
ed_outcome <- as.factor(ifelse(ed_for_log_reg$ed == "Yes",
1,
0))
ed_lr_roc <-
pROC::roc(ed_outcome, ed_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(ed_lr_roc)
## Area under the curve: 0.5042
ci.auc(ed_lr_roc)
## 95% CI: 0.4278-0.5805 (DeLong)
ed_lr_roc_data <- cbind(sensitivities = ed_lr_roc$sensitivities,
specificities = ed_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(ed_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
ed_lr_predict2 <- as_tibble(ed_lr_predict) %>% cbind(ed_for_log_reg) %>% subset(select = c(
value,
ed,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
ed_lr_predict2$ed <- ifelse(ed_lr_predict2$ed == "Yes", 1, 0)
ed_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(ed_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = ed_lr_predict2,
obs = "ed",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for ed Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier_score <- brier(ed_lr, ed_for_log_reg2, "ed")
## Warning in obs - probs: longer object length is not a multiple of shorter
## object length
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.215 |
pseudoR2_logistf(ed_lr, ed_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.226 |
n1 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & waisting_shortening == "Yes")) / n1
n2 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(waisting_shortening_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & waisting_shortening == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative waisting_shortening")
power
| Power Calculation Results for Post-Operative waisting_shortening | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.08 |
| Group 2 Proportion (p2) | 0.07 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 1.70 |
waisting_shortening_for_log_reg <- waisting_shortening_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(waisting_shortening = waisting_shortening %>% factor(levels = c("Yes",
"No")))
waisting_shortening_for_log_reg2 <- waisting_shortening_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
waisting_shortening = case_when(waisting_shortening == "Yes" ~ 1,
waisting_shortening == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
waisting_shortening,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
locality,
mechanism_of_injury
) %>% drop_na()
waisting_shortening_lr <- logistf(
waisting_shortening ~ presentation_to_knife_to_skin + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + locality + laterality + mechanism_of_injury,
data = waisting_shortening_for_log_reg2
)
waisting_shortening_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
presentation_to_knife_to_skin = "Time from Presentation to Theatre (6 Hour Blocks)",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(waisting_shortening_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Time from Presentation to Theatre (6 Hour Blocks) | 0.95 | 0.69, 1.26 | 0.7 |
| Imaging | |||
| No | — | — | |
| Yes | 0.47 | 0.08, 2.26 | 0.3 |
| Centre Volume | 1.02 | 0.97, 1.08 | 0.4 |
| Age at Time of Injury | 1.02 | 0.96, 1.09 | 0.6 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.72 | 0.31, 7.35 | 0.5 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 0.59 | 0.09, 3.04 | 0.5 |
| Site of Injury | |||
| Crura | — | — | |
| Distal | 0.10 | 0.00, 30.2 | 0.4 |
| Mid | 0.36 | 0.01, 76.1 | 0.6 |
| Multi-level | 0.36 | 0.00, 106 | 0.7 |
| Proximal | 0.57 | 0.01, 116 | 0.8 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.25 | 0.05, 1.14 | 0.072 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.45 | 0.00, 8.59 | 0.6 |
| Non-sexual blunt force trauma | 0.30 | 0.00, 3.13 | 0.4 |
| Masturbation injury | 2.03 | 0.01, 41.8 | 0.7 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 101 | |||
waisting_shortening_lr_predict <-
predict(waisting_shortening_lr, waisting_shortening_for_log_reg, type = "response")
waisting_shortening_outcome <- as.factor(ifelse(waisting_shortening_for_log_reg$waisting_shortening == "Yes",
1,
0))
waisting_shortening_lr_roc <-
pROC::roc(waisting_shortening_outcome, waisting_shortening_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls > cases
auc(waisting_shortening_lr_roc)
## Area under the curve: 0.5429
ci.auc(waisting_shortening_lr_roc)
## 95% CI: 0.3802-0.7057 (DeLong)
waisting_shortening_lr_roc_data <- cbind(sensitivities = waisting_shortening_lr_roc$sensitivities,
specificities = waisting_shortening_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(waisting_shortening_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
waisting_shortening_lr_predict2 <- as_tibble(waisting_shortening_lr_predict) %>% cbind(waisting_shortening_for_log_reg) %>% subset(select = c(
value,
waisting_shortening,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
waisting_shortening_lr_predict2$waisting_shortening <- ifelse(waisting_shortening_lr_predict2$waisting_shortening == "Yes", 1, 0)
waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = waisting_shortening_lr_predict2,
obs = "waisting_shortening",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for waisting_shortening Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(waisting_shortening_lr, waisting_shortening_for_log_reg2, "waisting_shortening")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.094 |
pseudoR2_logistf(waisting_shortening_lr, waisting_shortening_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.2 |
n1 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No"))
p1 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "No" & abnormal_curvature == "Yes")) / n1
n2 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(abnormal_curvature_for_log_reg %>% subset(did_the_patient_get_to_theatre_within_24_hours_of_presentation == "Yes" & abnormal_curvature == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative abnormal_curvature")
power
| Power Calculation Results for Post-Operative abnormal_curvature | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.16 |
| Group 2 Proportion (p2) | 0.17 |
| Group 1 Size (n1) | 76.00 |
| Group 2 Size (n2) | 138.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 4.90 |
Multi-level removed as model would not separate
abnormal_curvature_for_log_reg <- abnormal_curvature_for_log_reg %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(abnormal_curvature = abnormal_curvature %>% factor(levels = c("Yes",
"No")))
abnormal_curvature_for_log_reg2 <- abnormal_curvature_for_log_reg %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
abnormal_curvature = case_when(abnormal_curvature == "Yes" ~ 1,
abnormal_curvature == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
abnormal_curvature,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
abnormal_curvature_lr <- logistf(
abnormal_curvature ~ presentation_to_knife_to_skin + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + laterality + mechanism_of_injury,
data = abnormal_curvature_for_log_reg2
)
abnormal_curvature_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
presentation_to_knife_to_skin = "Time from Presentation to Theatre (6 Hour Blocks)",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(abnormal_curvature_for_log_reg2)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Time from Presentation to Theatre (6 Hour Blocks) | 1.05 | 0.88, 1.26 | 0.6 |
| Imaging | |||
| No | — | — | |
| Yes | 0.37 | 0.11, 1.19 | 0.10 |
| Centre Volume | 1.02 | 0.98, 1.07 | 0.2 |
| Age at Time of Injury | 0.97 | 0.93, 1.02 | 0.2 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.11 | 0.33, 3.52 | 0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 2.14 | 0.71, 6.66 | 0.2 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.41 | 0.00, 5.88 | 0.6 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.32 | 0.00, 5.43 | 0.5 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.19 | 0.00, 2.76 | 0.2 |
| Crural location | |||
| No | — | — | |
| Yes | 0.09 | 0.00, 8.13 | 0.3 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.52 | 0.14, 1.84 | 0.3 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.56 | 0.00, 8.06 | 0.7 |
| Non-sexual blunt force trauma | 0.35 | 0.06, 1.54 | 0.2 |
| Masturbation injury | 0.20 | 0.00, 2.32 | 0.2 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 107 | |||
abnormal_curvature_lr_predict <-
predict(abnormal_curvature_lr, abnormal_curvature_for_log_reg, type = "response")
abnormal_curvature_outcome <- as.factor(ifelse(abnormal_curvature_for_log_reg$abnormal_curvature == "Yes",
1,
0))
abnormal_curvature_lr_roc <-
pROC::roc(abnormal_curvature_outcome, abnormal_curvature_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(abnormal_curvature_lr_roc)
## Area under the curve: 0.5337
ci.auc(abnormal_curvature_lr_roc)
## 95% CI: 0.4327-0.6347 (DeLong)
abnormal_curvature_lr_roc_data <- cbind(sensitivities = abnormal_curvature_lr_roc$sensitivities,
specificities = abnormal_curvature_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(abnormal_curvature_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
abnormal_curvature_lr_predict2 <- as_tibble(abnormal_curvature_lr_predict) %>% cbind(abnormal_curvature_for_log_reg) %>% subset(select = c(
value,
abnormal_curvature,
did_the_patient_get_to_theatre_within_24_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
abnormal_curvature_lr_predict2$abnormal_curvature <- ifelse(abnormal_curvature_lr_predict2$abnormal_curvature == "Yes", 1, 0)
abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation <- as.integer(abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_24_hours_of_presentation)
predtools::calibration_plot(
data = abnormal_curvature_lr_predict2,
obs = "abnormal_curvature",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for abnormal_curvature Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(abnormal_curvature_lr, abnormal_curvature_for_log_reg2, "abnormal_curvature")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.174 |
pseudoR2_logistf(abnormal_curvature_lr, abnormal_curvature_for_log_reg2)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.266 |
n1 <- nrow(pain_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No"))
p1 <- nrow(pain_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No" & pain == "Yes")) / n1
n2 <- nrow(pain_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(pain_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes" & pain == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Pain")
power
| Power Calculation Results for Post-Operative Pain | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.11 |
| Group 2 Proportion (p2) | 0.12 |
| Group 1 Size (n1) | 112.00 |
| Group 2 Size (n2) | 133.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 5.10 |
knife_to_skin1 <- knife_to_skin %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
pain_for_log_reg_18 <- pain_for_log_reg_18 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No")))
pain_for_log_reg_182 <- pain_for_log_reg_18 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 7920,
NA,
presentation_to_knife_to_skin / (60*6)
),
pain = case_when(pain == "Yes" ~ 1,
pain == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
pain,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_18_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
pain_lr <- logistf(
pain ~ did_the_patient_get_to_theatre_within_18_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = pain_for_log_reg_182
)
pain_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_18_hours_of_presentation = "Theatre within 18 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(pain_for_log_reg_182)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 18 hours of Presentation | |||
| No | — | — | |
| Yes | 1.51 | 0.51, 4.69 | 0.5 |
| Imaging | |||
| No | — | — | |
| Yes | 1.05 | 0.36, 3.18 | >0.9 |
| Centre Volume | 0.94 | 0.89, 0.99 | 0.009 |
| Age at Time of Injury | 1.03 | 0.99, 1.08 | 0.2 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.16 | 0.32, 3.73 | 0.8 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 4.26 | 1.32, 14.8 | 0.015 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.00 | 0.00, 7.11 | 0.14 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 8.13 | 0.2 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.00 | 0.00, 4.75 | 0.12 |
| Crural location | |||
| No | — | — | |
| Yes | 0.07 | 0.00, 32.8 | 0.4 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 1,429 | 0.25, 20,142,183 | 0.10 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.75 | 0.19, 3.45 | 0.7 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.97 | 0.01, 12.1 | >0.9 |
| Non-sexual blunt force trauma | 3.91 | 0.79, 17.5 | 0.091 |
| Masturbation injury | 4.89 | 0.65, 37.6 | 0.12 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 141 | |||
# Add back in to get 24hr cut-off: presentation_to_knife_to_skin,
# did_the_patient_get_to_theatre_within_18_hours_of_presentation
# time_from_injury_to_th
pain_lr_predict <-
predict(pain_lr, pain_for_log_reg_18, type = "response")
pain_outcome <- as.factor(ifelse(pain_for_log_reg_18$pain == "Yes",
1,
0))
pain_lr_roc <-
pROC::roc(pain_outcome, pain_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(pain_lr_roc)
## Area under the curve: 0.7865
ci.auc(pain_lr_roc)
## 95% CI: 0.6891-0.8839 (DeLong)
pain_lr_roc_data <- cbind(sensitivities = pain_lr_roc$sensitivities,
specificities = pain_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(pain_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
pain_lr_predict2 <- as_tibble(pain_lr_predict) %>% cbind(pain_for_log_reg_18) %>% subset(select = c(
value,
pain,
did_the_patient_get_to_theatre_within_18_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
pain_lr_predict2$pain <- ifelse(pain_lr_predict2$pain == "Yes", 1, 0)
pain_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation <- as.integer(pain_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = pain_lr_predict2,
obs = "pain",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for Pain Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(pain_lr, pain_for_log_reg_182, "pain")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.118 |
pseudoR2_logistf <- function(model, data) {
# Extract log-likelihoods
ll_full <- model$loglik["full"]
ll_null <- model$loglik["null"]
# Sample size
n <- nrow(data)
# Cox & Snell R²
R2_CS <- 1 - exp((2 / n) * (ll_null - ll_full))
# Nagelkerke R²
R2_N <- R2_CS / (1 - exp((2 / n) * ll_null))
R2_N <- R2_N %>% as_tibble()
x <- cbind(
"Score" = "Nagelkerke's R^2",
"Nagelkerke's R^2" = round(R2_N$value, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
# Return as a named list
return(
x
)
}
pseudoR2_logistf(pain_lr, pain_for_log_reg_182)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.25 |
n1 <- nrow(ed_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No"))
p1 <- nrow(ed_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No" & ed == "Yes")) / n1
n2 <- nrow(ed_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(ed_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes" & ed == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Erectile Dysfunction")
power
| Power Calculation Results for Post-Operative Erectile Dysfunction | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.16 |
| Group 2 Proportion (p2) | 0.16 |
| Group 1 Size (n1) | 112.00 |
| Group 2 Size (n2) | 133.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 2.20 |
ed_for_log_reg_18 <- ed_for_log_reg_18 %>%
left_join(knife_to_skin1, by = c("submission_id" = "submission_id")) %>%
mutate(ed = ed %>% factor(levels = c("No", "Yes")))
ed_for_log_reg_182 <- ed_for_log_reg_18 %>%
drop_na(
ed,
imaging,
volume_n,
did_the_patient_get_to_theatre_within_18_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>%
mutate(
ed = case_when(ed == "Yes" ~ 1,
ed == "No" ~ 0,
TRUE ~ NA_real_),
presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
.keep = "unused"
)
ed_lr <- logistf(
ed ~ did_the_patient_get_to_theatre_within_18_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = ed_for_log_reg_182
)
ed_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_18_hours_of_presentation = "Theatre within 18 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(ed_for_log_reg_182)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 18 hours of Presentation | |||
| No | — | — | |
| Yes | 0.78 | 0.31, 1.92 | 0.6 |
| Imaging | |||
| No | — | — | |
| Yes | 1.36 | 0.48, 3.97 | 0.6 |
| Centre Volume | 0.98 | 0.94, 1.01 | 0.3 |
| Age at Time of Injury | 1.02 | 0.98, 1.07 | 0.3 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 2.64 | 0.91, 7.93 | 0.074 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.76 | 0.56, 5.83 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 99.6 | 0.17, 256,830 | 0.2 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 63.6 | 0.15, 130,045 | 0.2 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 30.0 | 0.07, 61,226 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 21.3 | 0.11, 19,175 | 0.3 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 0.03 | 0.00, 55.2 | 0.4 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 5.10 | 1.16, 33.3 | 0.029 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.28 | 0.00, 3.88 | 0.4 |
| Non-sexual blunt force trauma | 0.25 | 0.03, 1.20 | 0.087 |
| Masturbation injury | 0.14 | 0.00, 1.27 | 0.088 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 136 | |||
# did_the_patient_get_to_theatre_within_18_hours_of_presentation,
ed_lr_predict <-
predict(ed_lr, ed_for_log_reg_18, type = "response")
ed_outcome <- as.factor(ifelse(ed_for_log_reg_18$ed == "Yes",
1,
0))
ed_lr_roc <-
pROC::roc(ed_outcome, ed_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(ed_lr_roc)
## Area under the curve: 0.7903
ci.auc(ed_lr_roc)
## 95% CI: 0.7089-0.8717 (DeLong)
ed_lr_roc_data <- cbind(sensitivities = ed_lr_roc$sensitivities,
specificities = ed_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(ed_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
ed_lr_predict2 <- as_tibble(ed_lr_predict) %>% cbind(ed_for_log_reg_18) %>% subset(select = c(
value,
ed,
did_the_patient_get_to_theatre_within_18_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
ed_lr_predict2$ed <- ifelse(ed_lr_predict2$ed == "Yes", 1, 0)
ed_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation <- as.integer(ed_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = ed_lr_predict2,
obs = "ed",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for ed Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier_score <- brier(ed_lr, ed_for_log_reg_182, "ed")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.161 |
pseudoR2_logistf(ed_lr, ed_for_log_reg_182)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.232 |
n1 <- nrow(waisting_shortening_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No"))
p1 <- nrow(waisting_shortening_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No" & waisting_shortening == "Yes")) / n1
n2 <- nrow(waisting_shortening_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(waisting_shortening_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes" & waisting_shortening == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative waisting_shortening")
power
| Power Calculation Results for Post-Operative waisting_shortening | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.09 |
| Group 2 Proportion (p2) | 0.05 |
| Group 1 Size (n1) | 112.00 |
| Group 2 Size (n2) | 133.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.10 |
waisting_shortening_for_log_reg_18 <- waisting_shortening_for_log_reg_18 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(waisting_shortening = waisting_shortening %>% factor(levels = c("Yes",
"No")))
waisting_shortening_for_log_reg_182 <- waisting_shortening_for_log_reg_18 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
waisting_shortening = case_when(waisting_shortening == "Yes" ~ 1,
waisting_shortening == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
waisting_shortening,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_18_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
locality,
mechanism_of_injury
) %>% drop_na()
waisting_shortening_lr <- logistf(
waisting_shortening ~ did_the_patient_get_to_theatre_within_18_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + locality + laterality + mechanism_of_injury,
data = waisting_shortening_for_log_reg_182
)
waisting_shortening_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_18_hours_of_presentation = "Theatre within 18 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(waisting_shortening_for_log_reg_182)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 18 hours of Presentation | |||
| No | — | — | |
| Yes | 0.44 | 0.11, 1.51 | 0.2 |
| Imaging | |||
| No | — | — | |
| Yes | 0.38 | 0.07, 1.60 | 0.2 |
| Centre Volume | 1.01 | 0.96, 1.06 | 0.6 |
| Age at Time of Injury | 1.00 | 0.95, 1.06 | >0.9 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 0.88 | 0.16, 3.60 | 0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 0.73 | 0.13, 3.47 | 0.7 |
| Site of Injury | |||
| Crura | — | — | |
| Distal | 0.56 | 0.01, 123 | 0.8 |
| Mid | 0.99 | 0.03, 194 | >0.9 |
| Multi-level | 0.76 | 0.00, 223 | >0.9 |
| Proximal | 1.02 | 0.03, 197 | >0.9 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.34 | 0.08, 1.48 | 0.15 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.48 | 0.00, 7.84 | 0.7 |
| Non-sexual blunt force trauma | 0.18 | 0.00, 1.91 | 0.2 |
| Masturbation injury | 0.21 | 0.00, 2.65 | 0.3 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 119 | |||
waisting_shortening_lr_predict <-
predict(waisting_shortening_lr, waisting_shortening_for_log_reg_18, type = "response")
waisting_shortening_outcome <- as.factor(ifelse(waisting_shortening_for_log_reg_18$waisting_shortening == "Yes",
1,
0))
waisting_shortening_lr_roc <-
pROC::roc(waisting_shortening_outcome, waisting_shortening_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(waisting_shortening_lr_roc)
## Area under the curve: 0.7673
ci.auc(waisting_shortening_lr_roc)
## 95% CI: 0.6452-0.8894 (DeLong)
waisting_shortening_lr_roc_data <- cbind(sensitivities = waisting_shortening_lr_roc$sensitivities,
specificities = waisting_shortening_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(waisting_shortening_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
waisting_shortening_lr_predict2 <- as_tibble(waisting_shortening_lr_predict) %>% cbind(waisting_shortening_for_log_reg_18) %>% subset(select = c(
value,
waisting_shortening,
did_the_patient_get_to_theatre_within_18_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
waisting_shortening_lr_predict2$waisting_shortening <- ifelse(waisting_shortening_lr_predict2$waisting_shortening == "Yes", 1, 0)
waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation <- as.integer(waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = waisting_shortening_lr_predict2,
obs = "waisting_shortening",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for waisting_shortening Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(waisting_shortening_lr, waisting_shortening_for_log_reg_182, "waisting_shortening")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.1 |
pseudoR2_logistf(waisting_shortening_lr, waisting_shortening_for_log_reg_182)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.157 |
n1 <- nrow(abnormal_curvature_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No"))
p1 <- nrow(abnormal_curvature_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "No" & abnormal_curvature == "Yes")) / n1
n2 <- nrow(abnormal_curvature_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(abnormal_curvature_for_log_reg_18 %>% subset(did_the_patient_get_to_theatre_within_18_hours_of_presentation == "Yes" & abnormal_curvature == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative abnormal_curvature")
power
| Power Calculation Results for Post-Operative abnormal_curvature | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.18 |
| Group 2 Proportion (p2) | 0.14 |
| Group 1 Size (n1) | 112.00 |
| Group 2 Size (n2) | 133.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.30 |
Multi-level removed as model failed to separate
abnormal_curvature_for_log_reg_18 <- abnormal_curvature_for_log_reg_18 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(abnormal_curvature = abnormal_curvature %>% factor(levels = c("Yes",
"No")))
abnormal_curvature_for_log_reg_182 <- abnormal_curvature_for_log_reg_18 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
abnormal_curvature = case_when(abnormal_curvature == "Yes" ~ 1,
abnormal_curvature == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
abnormal_curvature,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_18_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
abnormal_curvature_lr <- logistf(
abnormal_curvature ~ did_the_patient_get_to_theatre_within_18_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + laterality + mechanism_of_injury,
data = abnormal_curvature_for_log_reg_182
)
abnormal_curvature_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_18_hours_of_presentation = "Theatre within 18 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(abnormal_curvature_for_log_reg_182)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 18 hours of Presentation | |||
| No | — | — | |
| Yes | 0.65 | 0.25, 1.63 | 0.4 |
| Imaging | |||
| No | — | — | |
| Yes | 0.37 | 0.12, 1.10 | 0.073 |
| Centre Volume | 1.03 | 0.99, 1.06 | 0.2 |
| Age at Time of Injury | 0.97 | 0.93, 1.01 | 0.15 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.10 | 0.36, 3.11 | 0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.77 | 0.59, 5.34 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.42 | 0.00, 5.93 | 0.6 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.40 | 0.00, 6.38 | 0.6 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.24 | 0.00, 3.43 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 0.09 | 0.00, 7.45 | 0.3 |
| laterality | |||
| Bilateral | — | — | |
| Unilateral | 0.56 | 0.16, 1.93 | 0.4 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.28 | 0.00, 3.29 | 0.4 |
| Non-sexual blunt force trauma | 0.44 | 0.09, 1.76 | 0.3 |
| Masturbation injury | 0.12 | 0.00, 1.09 | 0.062 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 128 | |||
abnormal_curvature_lr_predict <-
predict(abnormal_curvature_lr, abnormal_curvature_for_log_reg_18, type = "response")
abnormal_curvature_outcome <- as.factor(ifelse(abnormal_curvature_for_log_reg_18$abnormal_curvature == "Yes",
1,
0))
abnormal_curvature_lr_roc <-
pROC::roc(abnormal_curvature_outcome, abnormal_curvature_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(abnormal_curvature_lr_roc)
## Area under the curve: 0.7663
ci.auc(abnormal_curvature_lr_roc)
## 95% CI: 0.6832-0.8493 (DeLong)
abnormal_curvature_lr_roc_data <- cbind(sensitivities = abnormal_curvature_lr_roc$sensitivities,
specificities = abnormal_curvature_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(abnormal_curvature_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
abnormal_curvature_lr_predict2 <- as_tibble(abnormal_curvature_lr_predict) %>% cbind(abnormal_curvature_for_log_reg_18) %>% subset(select = c(
value,
abnormal_curvature,
did_the_patient_get_to_theatre_within_18_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
abnormal_curvature_lr_predict2$abnormal_curvature <- ifelse(abnormal_curvature_lr_predict2$abnormal_curvature == "Yes", 1, 0)
abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation <- as.integer(abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_18_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = abnormal_curvature_lr_predict2,
obs = "abnormal_curvature",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for abnormal_curvature Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(abnormal_curvature_lr, abnormal_curvature_for_log_reg_182, "abnormal_curvature")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.171 |
pseudoR2_logistf(abnormal_curvature_lr, abnormal_curvature_for_log_reg_182)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.229 |
n1 <- nrow(pain_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No"))
p1 <- nrow(pain_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No" & pain == "Yes")) / n1
n2 <- nrow(pain_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(pain_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes" & pain == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Pain")
power
| Power Calculation Results for Post-Operative Pain | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.07 |
| Group 2 Proportion (p2) | 0.12 |
| Group 1 Size (n1) | 45.00 |
| Group 2 Size (n2) | 200.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 26.10 |
knife_to_skin1 <- knife_to_skin %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
pain_for_log_reg_36 <- pain_for_log_reg_36 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No")))
pain_for_log_reg_362 <- pain_for_log_reg_36 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 7920,
NA,
presentation_to_knife_to_skin / (60*6)
),
pain = case_when(pain == "Yes" ~ 1,
pain == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
pain,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_36_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
pain_lr <- logistf(
pain ~ did_the_patient_get_to_theatre_within_36_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = pain_for_log_reg_362
)
pain_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_36_hours_of_presentation = "Theatre within 36 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(pain_for_log_reg_362)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 36 hours of Presentation | |||
| No | — | — | |
| Yes | 2.36 | 0.66, 11.3 | 0.2 |
| Imaging | |||
| No | — | — | |
| Yes | 1.00 | 0.36, 2.88 | >0.9 |
| Centre Volume | 0.94 | 0.89, 0.98 | 0.006 |
| Age at Time of Injury | 1.04 | 0.99, 1.09 | 0.13 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.22 | 0.34, 3.94 | 0.7 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 4.06 | 1.26, 14.0 | 0.019 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 28.3 | 0.3 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 27.1 | 0.3 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.01 | 0.00, 15.6 | 0.2 |
| Crural location | |||
| No | — | — | |
| Yes | 0.15 | 0.00, 75.7 | 0.5 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 508 | 0.07, 8,497,815 | 0.2 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.64 | 0.16, 2.91 | 0.5 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.69 | 0.00, 9.64 | 0.8 |
| Non-sexual blunt force trauma | 3.47 | 0.71, 15.4 | 0.12 |
| Masturbation injury | 4.62 | 0.67, 32.7 | 0.11 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 141 | |||
# Add back in to get 24hr cut-off: presentation_to_knife_to_skin,
# did_the_patient_get_to_theatre_within_36_hours_of_presentation
# time_from_injury_to_th
pain_lr_predict <-
predict(pain_lr, pain_for_log_reg_36, type = "response")
pain_outcome <- as.factor(ifelse(pain_for_log_reg_36$pain == "Yes",
1,
0))
pain_lr_roc <-
pROC::roc(pain_outcome, pain_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(pain_lr_roc)
## Area under the curve: 0.7904
ci.auc(pain_lr_roc)
## 95% CI: 0.7005-0.8804 (DeLong)
pain_lr_roc_data <- cbind(sensitivities = pain_lr_roc$sensitivities,
specificities = pain_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(pain_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
pain_lr_predict2 <- as_tibble(pain_lr_predict) %>% cbind(pain_for_log_reg_36) %>% subset(select = c(
value,
pain,
did_the_patient_get_to_theatre_within_36_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
pain_lr_predict2$pain <- ifelse(pain_lr_predict2$pain == "Yes", 1, 0)
pain_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation <- as.integer(pain_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = pain_lr_predict2,
obs = "pain",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for Pain Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(pain_lr, pain_for_log_reg_362, "pain")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.117 |
pseudoR2_logistf <- function(model, data) {
# Extract log-likelihoods
ll_full <- model$loglik["full"]
ll_null <- model$loglik["null"]
# Sample size
n <- nrow(data)
# Cox & Snell R²
R2_CS <- 1 - exp((2 / n) * (ll_null - ll_full))
# Nagelkerke R²
R2_N <- R2_CS / (1 - exp((2 / n) * ll_null))
R2_N <- R2_N %>% as_tibble()
x <- cbind(
"Score" = "Nagelkerke's R^2",
"Nagelkerke's R^2" = round(R2_N$value, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
# Return as a named list
return(
x
)
}
pseudoR2_logistf(pain_lr, pain_for_log_reg_362)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.263 |
n1 <- nrow(ed_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No"))
p1 <- nrow(ed_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No" & ed == "Yes")) / n1
n2 <- nrow(ed_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(ed_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes" & ed == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Erectile Dysfunction")
power
| Power Calculation Results for Post-Operative Erectile Dysfunction | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.27 |
| Group 2 Proportion (p2) | 0.14 |
| Group 1 Size (n1) | 45.00 |
| Group 2 Size (n2) | 200.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.00 |
ed_for_log_reg_36 <- ed_for_log_reg_36 %>%
left_join(knife_to_skin1, by = c("submission_id" = "submission_id")) %>%
mutate(ed = ed %>% factor(levels = c("No", "Yes")))
ed_for_log_reg_362 <- ed_for_log_reg_36 %>%
drop_na(
ed,
imaging,
volume_n,
did_the_patient_get_to_theatre_within_36_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>%
mutate(
ed = case_when(ed == "Yes" ~ 1,
ed == "No" ~ 0,
TRUE ~ NA_real_),
presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
.keep = "unused"
)
ed_lr <- logistf(
ed ~ did_the_patient_get_to_theatre_within_36_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = ed_for_log_reg_362
)
ed_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_36_hours_of_presentation = "Theatre within 36 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(ed_for_log_reg_362)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 36 hours of Presentation | |||
| No | — | — | |
| Yes | 0.37 | 0.13, 1.03 | 0.057 |
| Imaging | |||
| No | — | — | |
| Yes | 1.11 | 0.39, 3.24 | 0.8 |
| Centre Volume | 0.98 | 0.94, 1.02 | 0.3 |
| Age at Time of Injury | 1.02 | 0.98, 1.06 | 0.4 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 3.03 | 1.00, 9.63 | 0.051 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.88 | 0.60, 6.25 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 40.0 | 0.06, 108,356 | 0.3 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 27.3 | 0.05, 58,756 | 0.3 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 11.7 | 0.02, 25,461 | 0.5 |
| Crural location | |||
| No | — | — | |
| Yes | 12.9 | 0.06, 11,323 | 0.4 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 0.07 | 0.00, 167 | 0.5 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 7.04 | 1.45, 53.2 | 0.013 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.28 | 0.00, 4.42 | 0.4 |
| Non-sexual blunt force trauma | 0.29 | 0.03, 1.43 | 0.14 |
| Masturbation injury | 0.12 | 0.00, 1.26 | 0.085 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 136 | |||
# did_the_patient_get_to_theatre_within_36_hours_of_presentation,
ed_lr_predict <-
predict(ed_lr, ed_for_log_reg_36, type = "response")
ed_outcome <- as.factor(ifelse(ed_for_log_reg_36$ed == "Yes",
1,
0))
ed_lr_roc <-
pROC::roc(ed_outcome, ed_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(ed_lr_roc)
## Area under the curve: 0.8143
ci.auc(ed_lr_roc)
## 95% CI: 0.7345-0.8941 (DeLong)
ed_lr_roc_data <- cbind(sensitivities = ed_lr_roc$sensitivities,
specificities = ed_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(ed_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
ed_lr_predict2 <- as_tibble(ed_lr_predict) %>% cbind(ed_for_log_reg_36) %>% subset(select = c(
value,
ed,
did_the_patient_get_to_theatre_within_36_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
ed_lr_predict2$ed <- ifelse(ed_lr_predict2$ed == "Yes", 1, 0)
ed_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation <- as.integer(ed_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = ed_lr_predict2,
obs = "ed",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for ed Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier_score <- brier(ed_lr, ed_for_log_reg_362, "ed")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.155 |
pseudoR2_logistf(ed_lr, ed_for_log_reg_362)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.265 |
n1 <- nrow(waisting_shortening_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No"))
p1 <- nrow(waisting_shortening_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No" & waisting_shortening == "Yes")) / n1
n2 <- nrow(waisting_shortening_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(waisting_shortening_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes" & waisting_shortening == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative waisting_shortening")
power
| Power Calculation Results for Post-Operative waisting_shortening | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.07 |
| Group 2 Proportion (p2) | 0.07 |
| Group 1 Size (n1) | 45.00 |
| Group 2 Size (n2) | 200.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 3.00 |
waisting_shortening_for_log_reg_36 <- waisting_shortening_for_log_reg_36 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(waisting_shortening = waisting_shortening %>% factor(levels = c("Yes",
"No")))
waisting_shortening_for_log_reg_362 <- waisting_shortening_for_log_reg_36 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
waisting_shortening = case_when(waisting_shortening == "Yes" ~ 1,
waisting_shortening == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
waisting_shortening,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_36_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
locality,
mechanism_of_injury
) %>% drop_na()
waisting_shortening_lr <- logistf(
waisting_shortening ~ did_the_patient_get_to_theatre_within_36_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + locality + laterality + mechanism_of_injury,
data = waisting_shortening_for_log_reg_362
)
waisting_shortening_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_36_hours_of_presentation = "Theatre within 36 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(waisting_shortening_for_log_reg_362)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 36 hours of Presentation | |||
| No | — | — | |
| Yes | 1.12 | 0.28, 5.30 | 0.9 |
| Imaging | |||
| No | — | — | |
| Yes | 0.59 | 0.14, 2.37 | 0.5 |
| Centre Volume | 1.01 | 0.96, 1.06 | 0.6 |
| Age at Time of Injury | 1.01 | 0.95, 1.07 | 0.7 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 0.96 | 0.18, 3.78 | >0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 0.61 | 0.11, 2.82 | 0.5 |
| Site of Injury | |||
| Crura | — | — | |
| Distal | 0.43 | 0.01, 94.3 | 0.7 |
| Mid | 0.76 | 0.02, 145 | 0.9 |
| Multi-level | 0.45 | 0.00, 123 | 0.7 |
| Proximal | 0.67 | 0.02, 127 | 0.8 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.30 | 0.07, 1.25 | 0.10 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.48 | 0.00, 6.88 | 0.6 |
| Non-sexual blunt force trauma | 0.24 | 0.00, 2.15 | 0.2 |
| Masturbation injury | 0.32 | 0.00, 3.53 | 0.4 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 119 | |||
waisting_shortening_lr_predict <-
predict(waisting_shortening_lr, waisting_shortening_for_log_reg_36, type = "response")
waisting_shortening_outcome <- as.factor(ifelse(waisting_shortening_for_log_reg_36$waisting_shortening == "Yes",
1,
0))
waisting_shortening_lr_roc <-
pROC::roc(waisting_shortening_outcome, waisting_shortening_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(waisting_shortening_lr_roc)
## Area under the curve: 0.7667
ci.auc(waisting_shortening_lr_roc)
## 95% CI: 0.6419-0.8915 (DeLong)
waisting_shortening_lr_roc_data <- cbind(sensitivities = waisting_shortening_lr_roc$sensitivities,
specificities = waisting_shortening_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(waisting_shortening_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
waisting_shortening_lr_predict2 <- as_tibble(waisting_shortening_lr_predict) %>% cbind(waisting_shortening_for_log_reg_36) %>% subset(select = c(
value,
waisting_shortening,
did_the_patient_get_to_theatre_within_36_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
waisting_shortening_lr_predict2$waisting_shortening <- ifelse(waisting_shortening_lr_predict2$waisting_shortening == "Yes", 1, 0)
waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation <- as.integer(waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = waisting_shortening_lr_predict2,
obs = "waisting_shortening",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for waisting_shortening Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(waisting_shortening_lr, waisting_shortening_for_log_reg_362, "waisting_shortening")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.102 |
pseudoR2_logistf(waisting_shortening_lr, waisting_shortening_for_log_reg_362)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.128 |
n1 <- nrow(abnormal_curvature_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No"))
p1 <- nrow(abnormal_curvature_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "No" & abnormal_curvature == "Yes")) / n1
n2 <- nrow(abnormal_curvature_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(abnormal_curvature_for_log_reg_36 %>% subset(did_the_patient_get_to_theatre_within_36_hours_of_presentation == "Yes" & abnormal_curvature == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative abnormal_curvature")
power
| Power Calculation Results for Post-Operative abnormal_curvature | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.20 |
| Group 2 Proportion (p2) | 0.15 |
| Group 1 Size (n1) | 45.00 |
| Group 2 Size (n2) | 200.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.30 |
Multi-level removed as model failed to separate
abnormal_curvature_for_log_reg_36 <- abnormal_curvature_for_log_reg_36 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(abnormal_curvature = abnormal_curvature %>% factor(levels = c("Yes",
"No")))
abnormal_curvature_for_log_reg_362 <- abnormal_curvature_for_log_reg_36 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
abnormal_curvature = case_when(abnormal_curvature == "Yes" ~ 1,
abnormal_curvature == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
abnormal_curvature,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_36_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
abnormal_curvature_lr <- logistf(
abnormal_curvature ~ did_the_patient_get_to_theatre_within_36_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + laterality + mechanism_of_injury,
data = abnormal_curvature_for_log_reg_362
)
abnormal_curvature_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_36_hours_of_presentation = "Theatre within 36 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(abnormal_curvature_for_log_reg_362)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 36 hours of Presentation | |||
| No | — | — | |
| Yes | 0.49 | 0.17, 1.41 | 0.2 |
| Imaging | |||
| No | — | — | |
| Yes | 0.36 | 0.11, 1.04 | 0.060 |
| Centre Volume | 1.03 | 0.99, 1.07 | 0.11 |
| Age at Time of Injury | 0.97 | 0.92, 1.01 | 0.11 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.07 | 0.35, 3.05 | >0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.73 | 0.58, 5.25 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.39 | 0.00, 5.49 | 0.5 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.39 | 0.00, 6.05 | 0.5 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.24 | 0.00, 3.35 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 0.10 | 0.00, 8.89 | 0.3 |
| laterality | |||
| Bilateral | — | — | |
| Unilateral | 0.57 | 0.17, 1.93 | 0.4 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.29 | 0.00, 3.78 | 0.4 |
| Non-sexual blunt force trauma | 0.47 | 0.10, 1.92 | 0.3 |
| Masturbation injury | 0.12 | 0.00, 1.12 | 0.066 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 128 | |||
abnormal_curvature_lr_predict <-
predict(abnormal_curvature_lr, abnormal_curvature_for_log_reg_36, type = "response")
abnormal_curvature_outcome <- as.factor(ifelse(abnormal_curvature_for_log_reg_36$abnormal_curvature == "Yes",
1,
0))
abnormal_curvature_lr_roc <-
pROC::roc(abnormal_curvature_outcome, abnormal_curvature_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(abnormal_curvature_lr_roc)
## Area under the curve: 0.7712
ci.auc(abnormal_curvature_lr_roc)
## 95% CI: 0.6865-0.8558 (DeLong)
abnormal_curvature_lr_roc_data <- cbind(sensitivities = abnormal_curvature_lr_roc$sensitivities,
specificities = abnormal_curvature_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(abnormal_curvature_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
abnormal_curvature_lr_predict2 <- as_tibble(abnormal_curvature_lr_predict) %>% cbind(abnormal_curvature_for_log_reg_36) %>% subset(select = c(
value,
abnormal_curvature,
did_the_patient_get_to_theatre_within_36_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
abnormal_curvature_lr_predict2$abnormal_curvature <- ifelse(abnormal_curvature_lr_predict2$abnormal_curvature == "Yes", 1, 0)
abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation <- as.integer(abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_36_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = abnormal_curvature_lr_predict2,
obs = "abnormal_curvature",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for abnormal_curvature Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(abnormal_curvature_lr, abnormal_curvature_for_log_reg_362, "abnormal_curvature")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.169 |
pseudoR2_logistf(abnormal_curvature_lr, abnormal_curvature_for_log_reg_362)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.238 |
n1 <- nrow(pain_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No"))
p1 <- nrow(pain_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No" & pain == "Yes")) / n1
n2 <- nrow(pain_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(pain_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes" & pain == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Pain")
power
| Power Calculation Results for Post-Operative Pain | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.03 |
| Group 2 Proportion (p2) | 0.13 |
| Group 1 Size (n1) | 32.00 |
| Group 2 Size (n2) | 213.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 69.50 |
knife_to_skin1 <- knife_to_skin %>%
subset(select = c(
submission_id,
time_from_injury_to_th
))
pain_for_log_reg_48 <- pain_for_log_reg_48 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(pain = pain %>% factor(levels = c("Yes",
"No")))
pain_for_log_reg_482 <- pain_for_log_reg_48 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 7920,
NA,
presentation_to_knife_to_skin / (60*6)
),
pain = case_when(pain == "Yes" ~ 1,
pain == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
pain,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_48_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
pain_lr <- logistf(
pain ~ did_the_patient_get_to_theatre_within_48_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = pain_for_log_reg_482
)
pain_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_48_hours_of_presentation = "Theatre within 48 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
laterality = "Side of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(pain_for_log_reg_482)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 48 hours of Presentation | |||
| No | — | — | |
| Yes | 5.73 | 1.01, 86.9 | 0.048 |
| Imaging | |||
| No | — | — | |
| Yes | 0.90 | 0.32, 2.60 | 0.8 |
| Centre Volume | 0.94 | 0.89, 0.98 | 0.005 |
| Age at Time of Injury | 1.04 | 0.99, 1.09 | 0.13 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.27 | 0.33, 4.32 | 0.7 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 3.89 | 1.21, 13.5 | 0.023 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.03 | 0.00, 107 | 0.4 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.04 | 0.00, 81.7 | 0.4 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.02 | 0.00, 43.0 | 0.3 |
| Crural location | |||
| No | — | — | |
| Yes | 0.43 | 0.00, 263 | 0.8 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 182 | 0.02, 3,307,433 | 0.3 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.58 | 0.14, 2.66 | 0.5 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.67 | 0.00, 8.98 | 0.8 |
| Non-sexual blunt force trauma | 3.80 | 0.77, 17.2 | 0.10 |
| Masturbation injury | 6.68 | 0.88, 60.1 | 0.066 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 141 | |||
# Add back in to get 24hr cut-off: presentation_to_knife_to_skin,
# did_the_patient_get_to_theatre_within_48_hours_of_presentation
# time_from_injury_to_th
pain_lr_predict <-
predict(pain_lr, pain_for_log_reg_48, type = "response")
pain_outcome <- as.factor(ifelse(pain_for_log_reg_48$pain == "Yes",
1,
0))
pain_lr_roc <-
pROC::roc(pain_outcome, pain_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(pain_lr_roc)
## Area under the curve: 0.8
ci.auc(pain_lr_roc)
## 95% CI: 0.7044-0.8957 (DeLong)
pain_lr_roc_data <- cbind(sensitivities = pain_lr_roc$sensitivities,
specificities = pain_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(pain_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
pain_lr_predict2 <- as_tibble(pain_lr_predict) %>% cbind(pain_for_log_reg_48) %>% subset(select = c(
value,
pain,
did_the_patient_get_to_theatre_within_48_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
pain_lr_predict2$pain <- ifelse(pain_lr_predict2$pain == "Yes", 1, 0)
pain_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation <- as.integer(pain_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = pain_lr_predict2,
obs = "pain",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for Pain Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(pain_lr, pain_for_log_reg_482, "pain")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.112 |
pseudoR2_logistf <- function(model, data) {
# Extract log-likelihoods
ll_full <- model$loglik["full"]
ll_null <- model$loglik["null"]
# Sample size
n <- nrow(data)
# Cox & Snell R²
R2_CS <- 1 - exp((2 / n) * (ll_null - ll_full))
# Nagelkerke R²
R2_N <- R2_CS / (1 - exp((2 / n) * ll_null))
R2_N <- R2_N %>% as_tibble()
x <- cbind(
"Score" = "Nagelkerke's R^2",
"Nagelkerke's R^2" = round(R2_N$value, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
# Return as a named list
return(
x
)
}
pseudoR2_logistf(pain_lr, pain_for_log_reg_482)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.288 |
n1 <- nrow(ed_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No"))
p1 <- nrow(ed_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No" & ed == "Yes")) / n1
n2 <- nrow(ed_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(ed_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes" & ed == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative Erectile Dysfunction")
power
| Power Calculation Results for Post-Operative Erectile Dysfunction | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.28 |
| Group 2 Proportion (p2) | 0.14 |
| Group 1 Size (n1) | 32.00 |
| Group 2 Size (n2) | 213.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.00 |
ed_for_log_reg_48 <- ed_for_log_reg_48 %>%
left_join(knife_to_skin1, by = c("submission_id" = "submission_id")) %>%
mutate(ed = ed %>% factor(levels = c("No", "Yes")))
ed_for_log_reg_482 <- ed_for_log_reg_48 %>%
drop_na(
ed,
imaging,
volume_n,
did_the_patient_get_to_theatre_within_48_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
presentation_to_knife_to_skin,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>%
mutate(
ed = case_when(ed == "Yes" ~ 1,
ed == "No" ~ 0,
TRUE ~ NA_real_),
presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
.keep = "unused"
)
ed_lr <- logistf(
ed ~ did_the_patient_get_to_theatre_within_48_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + multi_level + laterality + mechanism_of_injury,
data = ed_for_log_reg_482
)
ed_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_48_hours_of_presentation = "Theatre within 48 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
multi_level = "Multi-level Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(ed_for_log_reg_482)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 48 hours of Presentation | |||
| No | — | — | |
| Yes | 0.30 | 0.09, 0.98 | 0.047 |
| Imaging | |||
| No | — | — | |
| Yes | 1.22 | 0.45, 3.49 | 0.7 |
| Centre Volume | 0.98 | 0.95, 1.02 | 0.3 |
| Age at Time of Injury | 1.02 | 0.98, 1.07 | 0.3 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 2.97 | 0.98, 9.44 | 0.054 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.82 | 0.58, 6.10 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 19.6 | 0.02, 58,247 | 0.4 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 15.9 | 0.03, 36,660 | 0.4 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 6.79 | 0.01, 15,843 | 0.6 |
| Crural location | |||
| No | — | — | |
| Yes | 7.39 | 0.03, 6,895 | 0.5 |
| Multi-level Injury | |||
| No | — | — | |
| Yes | 0.14 | 0.00, 380 | 0.6 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 6.24 | 1.35, 45.5 | 0.017 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.30 | 0.00, 4.68 | 0.4 |
| Non-sexual blunt force trauma | 0.29 | 0.03, 1.38 | 0.13 |
| Masturbation injury | 0.11 | 0.00, 1.20 | 0.076 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 136 | |||
# did_the_patient_get_to_theatre_within_48_hours_of_presentation,
ed_lr_predict <-
predict(ed_lr, ed_for_log_reg_48, type = "response")
ed_outcome <- as.factor(ifelse(ed_for_log_reg_48$ed == "Yes",
1,
0))
ed_lr_roc <-
pROC::roc(ed_outcome, ed_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(ed_lr_roc)
## Area under the curve: 0.8157
ci.auc(ed_lr_roc)
## 95% CI: 0.7381-0.8933 (DeLong)
ed_lr_roc_data <- cbind(sensitivities = ed_lr_roc$sensitivities,
specificities = ed_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(ed_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
ed_lr_predict2 <- as_tibble(ed_lr_predict) %>% cbind(ed_for_log_reg_48) %>% subset(select = c(
value,
ed,
did_the_patient_get_to_theatre_within_48_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
ed_lr_predict2$ed <- ifelse(ed_lr_predict2$ed == "Yes", 1, 0)
ed_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation <- as.integer(ed_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = ed_lr_predict2,
obs = "ed",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for ed Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier_score <- brier(ed_lr, ed_for_log_reg_482, "ed")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.154 |
pseudoR2_logistf(ed_lr, ed_for_log_reg_482)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.268 |
n1 <- nrow(waisting_shortening_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No"))
p1 <- nrow(waisting_shortening_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No" & waisting_shortening == "Yes")) / n1
n2 <- nrow(waisting_shortening_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(waisting_shortening_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes" & waisting_shortening == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative waisting_shortening")
power
| Power Calculation Results for Post-Operative waisting_shortening | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.09 |
| Group 2 Proportion (p2) | 0.07 |
| Group 1 Size (n1) | 32.00 |
| Group 2 Size (n2) | 213.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.70 |
waisting_shortening_for_log_reg_48 <- waisting_shortening_for_log_reg_48 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(waisting_shortening = waisting_shortening %>% factor(levels = c("Yes",
"No")))
waisting_shortening_for_log_reg_482 <- waisting_shortening_for_log_reg_48 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
waisting_shortening = case_when(waisting_shortening == "Yes" ~ 1,
waisting_shortening == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
waisting_shortening,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_48_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
locality,
mechanism_of_injury
) %>% drop_na()
waisting_shortening_lr <- logistf(
waisting_shortening ~ did_the_patient_get_to_theatre_within_48_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + locality + laterality + mechanism_of_injury,
data = waisting_shortening_for_log_reg_482
)
waisting_shortening_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_48_hours_of_presentation = "Theatre within 48 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
laterality = "Side of Injury",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(waisting_shortening_for_log_reg_482)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 48 hours of Presentation | |||
| No | — | — | |
| Yes | 0.52 | 0.12, 2.47 | 0.4 |
| Imaging | |||
| No | — | — | |
| Yes | 0.49 | 0.12, 1.86 | 0.3 |
| Centre Volume | 1.02 | 0.97, 1.07 | 0.5 |
| Age at Time of Injury | 1.00 | 0.95, 1.06 | 0.9 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 0.95 | 0.18, 3.85 | >0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 0.62 | 0.12, 2.94 | 0.6 |
| Site of Injury | |||
| Crura | — | — | |
| Distal | 0.39 | 0.01, 84.5 | 0.7 |
| Mid | 0.76 | 0.02, 145 | 0.9 |
| Multi-level | 0.47 | 0.00, 130 | 0.8 |
| Proximal | 0.69 | 0.02, 130 | 0.8 |
| Side of Injury | |||
| Bilateral | — | — | |
| Unilateral | 0.31 | 0.07, 1.32 | 0.11 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.61 | 0.00, 8.60 | 0.7 |
| Non-sexual blunt force trauma | 0.23 | 0.00, 2.18 | 0.2 |
| Masturbation injury | 0.21 | 0.00, 2.93 | 0.3 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 119 | |||
waisting_shortening_lr_predict <-
predict(waisting_shortening_lr, waisting_shortening_for_log_reg_48, type = "response")
waisting_shortening_outcome <- as.factor(ifelse(waisting_shortening_for_log_reg_48$waisting_shortening == "Yes",
1,
0))
waisting_shortening_lr_roc <-
pROC::roc(waisting_shortening_outcome, waisting_shortening_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(waisting_shortening_lr_roc)
## Area under the curve: 0.7699
ci.auc(waisting_shortening_lr_roc)
## 95% CI: 0.6546-0.8852 (DeLong)
waisting_shortening_lr_roc_data <- cbind(sensitivities = waisting_shortening_lr_roc$sensitivities,
specificities = waisting_shortening_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(waisting_shortening_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
waisting_shortening_lr_predict2 <- as_tibble(waisting_shortening_lr_predict) %>% cbind(waisting_shortening_for_log_reg_48) %>% subset(select = c(
value,
waisting_shortening,
did_the_patient_get_to_theatre_within_48_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
waisting_shortening_lr_predict2$waisting_shortening <- ifelse(waisting_shortening_lr_predict2$waisting_shortening == "Yes", 1, 0)
waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation <- as.integer(waisting_shortening_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = waisting_shortening_lr_predict2,
obs = "waisting_shortening",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for waisting_shortening Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(waisting_shortening_lr, waisting_shortening_for_log_reg_482, "waisting_shortening")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.102 |
pseudoR2_logistf(waisting_shortening_lr, waisting_shortening_for_log_reg_482)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.14 |
n1 <- nrow(abnormal_curvature_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No"))
p1 <- nrow(abnormal_curvature_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "No" & abnormal_curvature == "Yes")) / n1
n2 <- nrow(abnormal_curvature_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes"))
alpha <- 0.05
p2 <- nrow(abnormal_curvature_for_log_reg_48 %>% subset(did_the_patient_get_to_theatre_within_48_hours_of_presentation == "Yes" & abnormal_curvature == "Yes")) / n2
power <- calculate_power_table(p1, p2, n1, n2, alpha, title = "Power Calculation Results for Post-Operative abnormal_curvature")
power
| Power Calculation Results for Post-Operative abnormal_curvature | |
| Based on Two Proportion Test | |
| Parameter | Value |
|---|---|
| Group 1 Proportion (p1) | 0.22 |
| Group 2 Proportion (p2) | 0.15 |
| Group 1 Size (n1) | 32.00 |
| Group 2 Size (n2) | 213.00 |
| Significance Level (alpha) | 0.05 |
| Calculated Power (%) | 0.20 |
Multi-level removed as model failed to separate
abnormal_curvature_for_log_reg_48 <- abnormal_curvature_for_log_reg_48 %>%
left_join(knife_to_skin1,
by = c("submission_id" = "submission_id")) %>%
mutate(abnormal_curvature = abnormal_curvature %>% factor(levels = c("Yes",
"No")))
abnormal_curvature_for_log_reg_482 <- abnormal_curvature_for_log_reg_48 %>%
mutate(presentation_to_knife_to_skin = ifelse(
presentation_to_knife_to_skin < 0 | presentation_to_knife_to_skin > 5000,
NA,
presentation_to_knife_to_skin / (60*6)
),
abnormal_curvature = case_when(abnormal_curvature == "Yes" ~ 1,
abnormal_curvature == "No" ~ 0,
TRUE ~ NA_real_),
.keep = "unused"
) %>%
select(
abnormal_curvature,
imaging,
volume_n,
what_age_was_the_patient_at_the_time_of_the_injury,
did_the_patient_get_to_theatre_within_48_hours_of_presentation,
what_age_was_the_patient_at_the_time_of_the_injury,
was_the_patient_transferred_from_another_hospital_for_surgical_repair,
was_a_urethral_injury_noted_at_surgery,
laterality,
distal,
proximal,
mid,
crura,
multi_level,
mechanism_of_injury
) %>% drop_na()
abnormal_curvature_lr <- logistf(
abnormal_curvature ~ did_the_patient_get_to_theatre_within_48_hours_of_presentation + imaging + volume_n +
what_age_was_the_patient_at_the_time_of_the_injury + was_a_urethral_injury_noted_at_surgery +
was_the_patient_transferred_from_another_hospital_for_surgical_repair + distal + proximal + mid +
crura + laterality + mechanism_of_injury,
data = abnormal_curvature_for_log_reg_482
)
abnormal_curvature_lr %>%
tbl_regression(
exponentiate = TRUE,
label = list(
did_the_patient_get_to_theatre_within_48_hours_of_presentation = "Theatre within 48 hours of Presentation",
was_a_urethral_injury_noted_at_surgery = "Urethral Injury",
was_the_patient_transferred_from_another_hospital_for_surgical_repair = "Transfer for Surgical Repair",
locality = "Site of Injury",
distal = "Distal Corpus Location",
proximal = "Proximal Corpus Location",
mid = "Mid Corpus Location",
crura = "Crural location",
mechanism_of_injury = "Mechanism of Injury",
what_age_was_the_patient_at_the_time_of_the_injury =
"Age at Time of Injury",
imaging = "Imaging",
volume_n = "Centre Volume"
)
) %>%
bold_labels() %>%
as_gt() %>%
tab_source_note(
md(glue(
"Number of patients in analysis: {nrow(abnormal_curvature_for_log_reg_482)}"
))
)
## ! `broom::tidy()` failed to tidy the model.
## ✔ `tidy_parameters()` used instead.
## ℹ Add `tidy_fun = broom.helpers::tidy_parameters` to quiet these messages.
| Characteristic | exp(Beta) | 95% CI | p-value |
|---|---|---|---|
| Theatre within 48 hours of Presentation | |||
| No | — | — | |
| Yes | 0.39 | 0.12, 1.23 | 0.11 |
| Imaging | |||
| No | — | — | |
| Yes | 0.38 | 0.13, 1.06 | 0.066 |
| Centre Volume | 1.03 | 0.99, 1.07 | 0.11 |
| Age at Time of Injury | 0.97 | 0.93, 1.01 | 0.14 |
| Urethral Injury | |||
| No | — | — | |
| Yes | 1.09 | 0.36, 3.12 | 0.9 |
| Transfer for Surgical Repair | |||
| No | — | — | |
| Yes | 1.75 | 0.58, 5.37 | 0.3 |
| Distal Corpus Location | |||
| No | — | — | |
| Yes | 0.38 | 0.00, 5.28 | 0.5 |
| Proximal Corpus Location | |||
| No | — | — | |
| Yes | 0.42 | 0.00, 6.69 | 0.6 |
| Mid Corpus Location | |||
| No | — | — | |
| Yes | 0.27 | 0.00, 3.79 | 0.4 |
| Crural location | |||
| No | — | — | |
| Yes | 0.11 | 0.00, 10.2 | 0.4 |
| laterality | |||
| Bilateral | — | — | |
| Unilateral | 0.56 | 0.17, 1.87 | 0.3 |
| Mechanism of Injury | |||
| Sexual intercourse trauma | — | — | |
| Other | 0.32 | 0.00, 3.96 | 0.4 |
| Non-sexual blunt force trauma | 0.47 | 0.10, 1.90 | 0.3 |
| Masturbation injury | 0.10 | 0.00, 1.06 | 0.057 |
| Abbreviation: CI = Confidence Interval | |||
| Number of patients in analysis: 128 | |||
abnormal_curvature_lr_predict <-
predict(abnormal_curvature_lr, abnormal_curvature_for_log_reg_48, type = "response")
abnormal_curvature_outcome <- as.factor(ifelse(abnormal_curvature_for_log_reg_48$abnormal_curvature == "Yes",
1,
0))
abnormal_curvature_lr_roc <-
pROC::roc(abnormal_curvature_outcome, abnormal_curvature_lr_predict)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(abnormal_curvature_lr_roc)
## Area under the curve: 0.778
ci.auc(abnormal_curvature_lr_roc)
## 95% CI: 0.696-0.8599 (DeLong)
abnormal_curvature_lr_roc_data <- cbind(sensitivities = abnormal_curvature_lr_roc$sensitivities,
specificities = abnormal_curvature_lr_roc$specificities) %>% as_tibble()
ggplot(as_tibble(abnormal_curvature_lr_roc_data), aes(x = 1 - specificities, y = sensitivities)) +
geom_line() +
geom_abline(slope = 1, intercept = 0, linetype = "dashed")
abnormal_curvature_lr_predict2 <- as_tibble(abnormal_curvature_lr_predict) %>% cbind(abnormal_curvature_for_log_reg_48) %>% subset(select = c(
value,
abnormal_curvature,
did_the_patient_get_to_theatre_within_48_hours_of_presentation
)) %>% mutate(
pred = value,
.keep = "unused"
)
abnormal_curvature_lr_predict2$abnormal_curvature <- ifelse(abnormal_curvature_lr_predict2$abnormal_curvature == "Yes", 1, 0)
abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation <- as.integer(abnormal_curvature_lr_predict2$did_the_patient_get_to_theatre_within_48_hours_of_presentation)
## Warning: NAs introduced by coercion
predtools::calibration_plot(
data = abnormal_curvature_lr_predict2,
obs = "abnormal_curvature",
pred = "pred",
y_lim = c(0, 1),
x_lim = c(0, 1),
title = "Calibration plot for abnormal_curvature Model"
)
## $calibration_plot
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_point()`).
brier <- function(model, data, outcome) {
probs <- predict(model, type = "response")
obs <- data[[outcome]]
mean((obs - probs)^2, na.rm = TRUE)
}
brier_score <- brier(abnormal_curvature_lr, abnormal_curvature_for_log_reg_482, "abnormal_curvature")
cbind(
"Score" = "Brier Score",
"Brier Score" = round(brier_score, digits = 3)
) %>% as_tibble() %>% gt() %>% gt_theme_espn()
| Score | Brier Score |
|---|---|
| Brier Score | 0.168 |
pseudoR2_logistf(abnormal_curvature_lr, abnormal_curvature_for_log_reg_482)
| Score | Nagelkerke's R^2 |
|---|---|
| Nagelkerke's R^2 | 0.247 |