Mace Paper

Author

Prof. Sarfo

Published

January 5, 2026

Housekeeping

Show the code
rm(list = ls(all = T))
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.6
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.1     ✔ tibble    3.3.0
✔ lubridate 1.9.4     ✔ tidyr     1.3.2
✔ purrr     1.2.0     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Show the code
library(gtsummary)
gtsummary::theme_gtsummary_eda()
Setting theme "Exploratory Data Analysis"

Read in Data

Show the code
df_pings2_bp <- 
    dget("pings_2_data_with_bps_ready") %>%
    mutate(
        female = a_gender == "Female", 
        nihss_levcon = str_extract(z_levcon, "^\\d+") %>% 
            as.numeric(),
        nihss_loc_quest = str_extract(z_loc_quest, "^\\d+") %>% 
            as.numeric(), 
        nihss_loc_comm = str_extract(z_loc_comm, "^\\d+") %>% 
            as.numeric(),
        nihss_bestgaze = str_extract(z_bestgaze, "^\\d+") %>% 
            as.numeric(),
        nihss_vfield = str_extract(z_vfield, "^\\d+") %>% 
            as.numeric(),
        nihss_facparesis = str_extract(z_facparesis, "^\\d+") %>% 
            as.numeric(),
        nihss_motor_armr = str_extract(z_motor_armr, "^\\d+") %>% 
            as.numeric(),
        nihss_motor_arml = str_extract(z_motor_arml, "^\\d+") %>% 
            as.numeric(),
        nihss_motor_legr = str_extract(z_motor_legr, "^\\d+") %>% 
            as.numeric(),
        nihss_motor_legl = str_extract(z_motor_legl, "^\\d+") %>% 
            as.numeric(),
        nihss_limbataxia = str_extract(z_limbataxia, "^\\d+") %>% 
            as.numeric(),
        nihss_pinprick = str_extract(z_pinprick, "^\\d+") %>% 
            as.numeric(),
        nihss_bestlang = str_extract(z_bestlang, "^\\d+") %>% 
            as.numeric(),
        nihss_dysarthria = str_extract(z_dysarthria, "^\\d+") %>% 
            as.numeric(),
        nihss_extinction = str_extract(z_extinction, "^\\d+") %>% 
            as.numeric(),
        nihss_scale = nihss_levcon + nihss_loc_quest + nihss_loc_comm + 
            nihss_bestgaze + nihss_vfield + nihss_facparesis + 
            nihss_motor_armr + nihss_motor_arml + nihss_motor_legr +
            nihss_motor_legl + nihss_limbataxia + nihss_pinprick + 
            nihss_bestlang + nihss_dysarthria + nihss_extinction, 
        ranking = str_extract(x_ranking, "\\d+") %>% 
            as.numeric(), 
        dm = case_when(
            ff_hba1c_0 > 6.5 ~ "Yes",  
            c_dm == "Yes" ~ "Yes",
            h_antidm == "Yes" ~ "Yes", 
            ff_fbs_0 > 7 ~ "Yes",
            eventname == "Baseline" ~ "No"),
        hba1c_high = case_when(
            ff_hba1c_0 < 6.5 ~ "No", 
            ff_hba1c_0 >= 6.5 ~ "Yes"),
        hpt = case_when(
            sbp >= 140 ~ "Yes", 
            dbp >= 90 ~ "Yes",
            sbp <  140 ~ "No",
            dbp <  90 ~ "No") %>%  factor(),
        hyperlipidemia = case_when(
            c_hyperlip == "Yes" ~ "Yes", 
            h_antilipid == "Yes" ~ "Yes",
            ff_totchol_0 > 5.17 ~ "Yes", 
            eventname == "Baseline" ~ "No"),
        tobacco_use = case_when(g_tobacco %in% c(
            "Formerly used tobacco products", 
            "Stopped after the stroke occurred", 
            "Currently uses tobacco products") ~ "Yes",
            g_tobacco == "Never used tobacco products" ~ "No"),
        obese_overwgt = case_when(
            ee_bmi_0 >= 25 ~ "Yes", 
            ee_bmi_0 < 25 ~ "No"),
        bmi_cat = case_when(
            ee_bmi_0 < 25 ~ "Normal", 
            ee_bmi_0 < 30 ~ "Overweight", 
            ee_bmi_0 >= 30 ~ "Obese") %>% 
            factor(levels = c("Normal", "Overweight", "Obese")),
        alcohol_curr = case_when(
            g_alcohol == "Currently uses alcohol" ~ "Yes",
            g_alcohol %in% c(
                "Never used alcohol", 
                "Past 12 months", 
                "Past 30 days", 
                "Formerly used alcohol", 
                "Stopped after the stroke occured") ~ "No"),
        acei = i_acei_v2 == "Checked",
        arb = i_arb_v2 == "Checked",
        bb = i_bb_v2 == "Checked",
        ccb = i_ccb_v2 == "Checked",
        h_alpha_md = i_alpha_md_v2 == "Checked",
        h_alpha_ab = i_alpha_ab_v2 == "Checked",
        diuretics = i_diuretics_v2 == "Checked",
        h_antiplt = i_antiplt_v2 == "Yes",
        h_statins = i_statins_v2 == "Yes",
        income2 = case_when(
            a_income %in% c("0-100", "101-250", "251-500") ~ "<500 GHc",
            a_income %in% c("501-1500", "1501-3000", "> 3000") ~ 
                ">= 500 GHc"),
        educ = fct_recode(a_formeduc, Tertiary = "Postgraduate"),
        educ2 = case_when(
            a_formeduc %in% c("None", "Primary") ~ "None/Primary",
            a_formeduc %in% c("Secondary", "Tertiary", "Postgraduate") ~ 
                "Secondary or higher"),
        agecat = case_when(
            a_agebase  < 60 ~ "<60", a_agebase >= 60 ~ ">=60"),
        hosp_cat = case_when(
            datagrp %in% c("CCTH SITE", "KATH SITE", "KORLE-BU SITE") ~ 
                "Tertiary",
            datagrp %in% c(
                "KUMASI SOUTH HOSPITAL", "AGOGO SITE", "KNUST SITE") ~ 
                "Secondary",
            datagrp %in% c(
                "ANKAASE SITE", "MANHYIA GOVT HOSPITAL", "KWADASO SITE",
                "TAFO SITE") ~ 
              "Primary"), 
        arm = case_when(
            arm == "Arm 1- Intervention Arm" ~ "Intervention", 
            arm == "Arm 2- Routine Care" ~ "Routine"),
        morisky_4_item = (unclass(k_forget) + unclass(k_miss) + 
            unclass(k_fine) + unclass(k_doctor)), 
        across(
            c(l_forget, l_decide, l_salty, l_shake, l_fasfood, l_appoint, 
            l_missched, l_prescrip, l_runout, l_skipmed, l_feelbet,
            l_feelsick, l_someone, l_careless), 
            .fns = ~factor(.x),
            .names = "{.col}_unclassed"),
        across(
            c(l_forget_unclassed, l_decide_unclassed, l_salty_unclassed, 
              l_shake_unclassed, l_fasfood_unclassed, l_appoint_unclassed, 
            l_missched_unclassed, l_prescrip_unclassed, l_runout_unclassed, 
            l_skipmed_unclassed, l_feelbet_unclassed, l_feelsick_unclassed, 
            l_someone_unclassed, l_careless_unclassed), 
            .fns = ~unclass(.x)),
        hillbone = (
            l_forget_unclassed + l_decide_unclassed + l_salty_unclassed + 
            l_shake_unclassed + l_fasfood_unclassed + l_appoint_unclassed + 
            l_missched_unclassed + l_prescrip_unclassed + 
            l_runout_unclassed + l_skipmed_unclassed + l_feelbet_unclassed + 
            l_feelsick_unclassed + l_someone_unclassed + 
                l_careless_unclassed) %>%  
            as.numeric(),
        aa_bp_115_75_corrrect = ifelse(
            aa_bp_115_75 == "Normal", "Yes", "No"),
        aa_bp160_100_correct = ifelse(
            aa_bp160_100 == "High", "Yes", "No"),
        aa_hptlasts_correct = ifelse(
            aa_hptlasts == "The Rest of their Life", "Yes", "No"),
        aa_hptmeds_correct = ifelse(aa_hptmeds == "Everyday", "Yes", "No"),
        aa_losewght_correct = ifelse(aa_losewght == "Go Down", "Yes", "No"),
        aa_eatsalt_correct = ifelse(aa_eatsalt == "Go Down", "Yes", "No"),
        aa_hrtattack_correct = ifelse(aa_hrtattack == "Yes", "Yes", "No"),
        aa_cancer_correct = ifelse(aa_cancer == "No", "Yes", "No"),
        aa_stroke_correct = ifelse(aa_stroke == "Yes", "Yes", "No"),
        aa_kidneyp_correct = ifelse(aa_kidneyp == "Yes", "Yes", "No"),
        aa_highrisk_correct = ifelse(aa_highrisk == "Yes", "Yes", "No"),
        aa_headache_correct = ifelse(aa_headache == "No", "Yes", "No"),
        aa_feelgood_correct = ifelse(aa_feelgood == "Never", "Yes", "No"),
        aa_strokeris_correct = ifelse(
            aa_strokeris == "The Rest of Their Life", "Yes", "No"),
        aa_hkq = (aa_bp_115_75_corrrect == "Yes") + 
            (aa_bp160_100_correct == "Yes") +
            (aa_hptlasts_correct =="Yes") + 
            (aa_hptmeds_correct == "Yes") + 
            (aa_losewght_correct == "Yes") + 
            (aa_eatsalt_correct == "Yes") + 
            (aa_hrtattack_correct == "Yes") + 
            (aa_cancer_correct == "Yes") + 
            (aa_stroke_correct == "Yes") + 
            (aa_kidneyp_correct == "Yes") + 
            (aa_highrisk_correct == "Yes") + 
            (aa_headache_correct =="Yes") + 
            (aa_feelgood_correct =="Yes") + 
            (aa_strokeris_correct == "Yes"),
        mobility = case_when(
            str_detect(
                p_mobility , "I have no problems in walking about") ~ "1",
            str_detect(
                p_mobility , "I have some problems in walking about") ~ "2",
            str_detect(
                p_mobility , "I am confined to bed") ~ "3")%>% 
            as.numeric(),
        selfcare = case_when(
            str_detect(
                p_selfcare , "I have no problems with self-care") ~ "1",
            str_detect(
                p_selfcare , "I have some problems with washing or") ~ "2",
            str_detect(
                p_selfcare , 
                "I am unable to wash or dress myself") ~ "3")%>%
            as.numeric(),
        usual_act = case_when(
            str_detect(
                p_usual_act , 
                "I have no problems with performing my") ~ "1",
            str_detect(
                p_usual_act , "I have some problems with performing") ~ "2",
            str_detect(
                p_usual_act , "I am unable to perform my usual activitie") ~
                "3")%>% 
            as.numeric(),
        pain_disc = case_when(
            str_detect(p_pain_disc , "I have no pain or discomfort") ~ "1",
            str_detect(
                p_pain_disc , "I have moderate pain or discomfort") ~ "2",
            str_detect(
                p_pain_disc , 
                "I have extreme pain or discomfort") ~ "3") %>%
            as.numeric(),
        anxiety = case_when(
            str_detect(p_anxiety, "I am not anxious or depressed") ~ "1",
            str_detect(
                p_anxiety, "I am moderately anxious or depressed") ~ "2",
            str_detect(
                p_anxiety, "I am extremely anxious or depressed") ~ "3")%>% 
            as.numeric(),
        eq_5d = mobility + selfcare + usual_act + pain_disc + anxiety,
         p_health = ifelse(p_health <= 1, p_health*100, p_health), 
        across(
            c(bb_physical, bb_nutfacts, bb_repsalt, bb_limsalt, bb_tabsalt, 
              bb_eatsfood, 
            bb_broilst, bb_rsfoods, bb_rephfat, bb_totcal, bb_eatveges, 
            bb_alcohol, bb_smoking, bb_bpathome, bb_fbpmeds, bb_takemeds,
            bb_wgtdown, bb_monitst, bb_streslow, bb_doctor, bb_physical2,
            bb_nutfacts2, bb_repsalt2,bb_limsalt2, bb_tabsalt2,
            bb_eatsfood2, bb_broilst2, bb_rsfoods2, bb_rephfat2, 
            bb_totcal2, bb_eatveges2, bb_alcohol2, bb_smoking2, 
            bb_bpathome2, bb_fbpmeds2, bb_takemeds2, bb_wgtdown2,
            bb_monitst2, bb_streslow2, bb_doctor2,  bb_physical3,
            bb_nutfacts3, bb_repsalt3, bb_limsalt3, bb_tabsalt3, 
            bb_eatsfood3, bb_broilst3, bb_rsfoods3, bb_rephfat3, 
            bb_totcal3, bb_eatveges3, bb_alcohol3, bb_smoking3,
            bb_bpathome3, bb_fbpmeds3, bb_takemeds3, bb_wgtdown3, 
            bb_monitst3, bb_streslow3, bb_doctor3), 
            .fns = ~factor(.x),
            .names = "{.col}_unclassed"),
        across(
            c(bb_physical_unclassed, bb_nutfacts_unclassed,
              bb_repsalt_unclassed, 
              bb_limsalt_unclassed, bb_tabsalt_unclassed,
              bb_eatsfood_unclassed, 
            bb_broilst_unclassed, bb_rsfoods_unclassed,
            bb_rephfat_unclassed, 
            bb_totcal_unclassed, bb_eatveges_unclassed, 
            bb_alcohol_unclassed, 
            bb_smoking_unclassed, bb_bpathome_unclassed,
            bb_fbpmeds_unclassed, 
            bb_takemeds_unclassed, bb_wgtdown_unclassed,
            bb_monitst_unclassed, 
            bb_streslow_unclassed, bb_doctor_unclassed,
            bb_physical2_unclassed, 
            bb_nutfacts2_unclassed, bb_repsalt2_unclassed,
            bb_limsalt2_unclassed, 
            bb_tabsalt2_unclassed, bb_eatsfood2_unclassed,
            bb_broilst2_unclassed, 
            bb_rsfoods2_unclassed, bb_rephfat2_unclassed,
            bb_totcal2_unclassed, 
            bb_eatveges2_unclassed, bb_alcohol2_unclassed,
            bb_smoking2_unclassed, 
            bb_bpathome2_unclassed, bb_fbpmeds2_unclassed,
            bb_takemeds2_unclassed, 
            bb_wgtdown2_unclassed, bb_monitst2_unclassed,
            bb_streslow2_unclassed, 
            bb_doctor2_unclassed, bb_physical3_unclassed,
            bb_nutfacts3_unclassed,
            bb_repsalt3_unclassed, bb_limsalt3_unclassed,
            bb_tabsalt3_unclassed, 
            bb_eatsfood3_unclassed, bb_broilst3_unclassed,
            bb_rsfoods3_unclassed, 
            bb_rephfat3_unclassed, bb_totcal3_unclassed,
            bb_eatveges3_unclassed, 
            bb_alcohol3_unclassed, bb_smoking3_unclassed,
            bb_bpathome3_unclassed, 
            bb_fbpmeds3_unclassed, bb_takemeds3_unclassed,
            bb_wgtdown3_unclassed, 
            bb_monitst3_unclassed, bb_streslow3_unclassed,
            bb_doctor3_unclassed), 
            .fns = ~unclass(.x)),
        across(
          c(bb_fbpmeds_unclassed, bb_takemeds_unclassed,
            bb_fbpmeds2_unclassed, bb_takemeds2_unclassed,
            bb_fbpmeds3_unclassed, bb_takemeds3_unclassed), 
          .fns = ~ 0 - .x + 5),
        hpt_self_care = bb_physical_unclassed + bb_nutfacts_unclassed + 
          bb_repsalt_unclassed + 
            bb_limsalt_unclassed + bb_tabsalt_unclassed + 
            bb_eatsfood_unclassed + 
            bb_broilst_unclassed + bb_rsfoods_unclassed + 
            bb_rephfat_unclassed + 
            bb_totcal_unclassed + bb_eatveges_unclassed + 
            bb_alcohol_unclassed + 
            bb_smoking_unclassed + bb_bpathome_unclassed + 
            bb_fbpmeds_unclassed + 
            bb_takemeds_unclassed + bb_wgtdown_unclassed + 
            bb_monitst_unclassed + 
            bb_streslow_unclassed + bb_doctor_unclassed + 
            bb_physical2_unclassed + 
            bb_nutfacts2_unclassed + bb_repsalt2_unclassed + 
            bb_limsalt2_unclassed + 
            bb_tabsalt2_unclassed + bb_eatsfood2_unclassed + 
            bb_broilst2_unclassed + 
            bb_rsfoods2_unclassed + bb_rephfat2_unclassed + 
            bb_totcal2_unclassed + 
            bb_eatveges2_unclassed + bb_alcohol2_unclassed +  
            bb_smoking2_unclassed + 
            bb_bpathome2_unclassed + bb_fbpmeds2_unclassed + 
            bb_takemeds2_unclassed + 
            bb_wgtdown2_unclassed + bb_monitst2_unclassed + 
            bb_streslow2_unclassed + 
            bb_doctor2_unclassed + bb_physical3_unclassed + 
            bb_nutfacts3_unclassed +
            bb_repsalt3_unclassed + bb_limsalt3_unclassed + 
            bb_tabsalt3_unclassed + 
            bb_eatsfood3_unclassed + bb_broilst3_unclassed + 
            bb_rsfoods3_unclassed + 
            bb_rephfat3_unclassed + bb_totcal3_unclassed + 
            bb_eatveges3_unclassed + 
            bb_alcohol3_unclassed + bb_smoking3_unclassed + 
            bb_bpathome3_unclassed + 
            bb_fbpmeds3_unclassed + bb_takemeds3_unclassed + 
            bb_wgtdown3_unclassed + 
            bb_monitst3_unclassed + bb_streslow3_unclassed + 
            bb_doctor3_unclassed, 
        sbp_2 = sbp, 
        dbp_2 = dbp, 
        sbp_baseline = case_when(eventname == "Baseline" ~ sbp),
        dbp_baseline = case_when(eventname == "Baseline" ~ dbp),
        stroke_type = case_when(
          d_st_type == "Ischemic Stroke" ~ "Ischemic",
          d_st_type == 
              "Intracerebral Hemorrhagic Stroke" ~ "Hemorrhagic") %>% 
          factor(),
        hosp_cat2 = case_when(
          hosp_cat %in% c("Primary","Secondary") ~ "Primary/Secondary",
          hosp_cat == "Tertiary" ~ "Tertiary"),
        egfr0 = parse_number(ff_egfr_0),
        egfr0 = ifelse(egfr0 < 1, egfr0*100, egfr0),
        egfr_cat = case_when(egfr0 < 60 ~ "<60", egfr0 >= 60 ~ ">=60"),
        across(
            c(m12_pratio_1, m12_pratio_2, m12_pratio_3, m12_pratio_4, 
            m12_pratio_5, m12_pratio_6, m12_pratio_7, m12_pratio_8), 
              ~parse_number(.)),
        emerg_visit = case_when(
          gg_emerg_0 == "seizure" ~ "Yes",
          gg_emerg_1 == "Stage III HPT" ~ "Yes", 
          gg_emerg_3 %in% c("Seizure","Yes") ~ "Yes", 
          gg_emerg_6 %in%  c("seizure (recurrent stroke)", "YES") ~ "Yes",
          eventname == "Baseline" ~ "No"),
        emerg_visit = emerg_visit == "Yes",
        mpr12 = rowMeans(
          across(
            c(m12_pratio_1, m12_pratio_2, m12_pratio_3, m12_pratio_4, 
              m12_pratio_5, m12_pratio_6, m12_pratio_7, m12_pratio_8)), 
            na.rm=T),
        mpr12 = ifelse(mpr12 < 10, mpr12*10, mpr12),
        mpr12 = ifelse(mpr12 > 200, mpr12/10, mpr12),
        mpr12 = ifelse(mpr12 > 100, 100, mpr12),
        sbp_gr_eq_160_baseline = case_when(
          sbp < 160 & eventname == "Baseline" ~ "<160mmHg",
          sbp >= 160 & eventname == "Baseline" ~ ">=160mmHg")) %>% 
      arrange(pid, eventname) %>% 
      group_by(pid) %>% 
      fill(
        sbp_2, dbp_2, arm, sbp_baseline, dbp_baseline, emerg_visit, dm, 
        d_st_type, arm) %>% 
      ungroup() %>% 
      mutate(
          sbp_less_140_itt = sbp_2 < 140, 
          sbp_less_140_pp = sbp < 140, 
          bp_less_140_90_itt = (sbp_2 < 140 & dbp_2 < 90),
          bp_less_140_90_pp = (sbp < 140 & dbp < 90),
          sbp_diff = sbp_baseline - sbp,
          dbp_diff = dbp_baseline - dbp,
          sbp_diff_itt = sbp_baseline - sbp_2,
          dbp_diff_itt = dbp_baseline - dbp_2,
          sbp_less_135_itt = sbp_2 < 135, 
          sbp_less_135_pp = sbp < 135,
          sbp_less_130_itt = sbp_2 < 130, 
          sbp_less_130_pp = sbp < 130, 
          review_no = case_when(
            eventname == "Baseline" & !is.na(sbp) ~ 0,
            eventname == "Month 1"  & !is.na(sbp) ~ 1,
            eventname == "Month 3" & !is.na(sbp) ~ 3,
            eventname == "Month 6"  & !is.na(sbp) ~ 6,
            eventname == "Month 9" & !is.na(sbp) ~ 9,
            eventname == "Month12" & !is.na(sbp) ~ 12),
          d_st_type_2 = fct_recode(
              d_st_type, 
              "Ischemic Stroke" = 
                  "Ischemic With Hemorrhagic Transformation")) %>% 
      arrange(pid, eventname) %>% 
      group_by(pid) %>% 
      mutate(
        max_review = max(review_no, na.rm = T),
        completed_study = case_when(
          max_review == 12 ~ "Yes", TRUE ~ "No") %>% factor()) %>% 
      ungroup()
Warning: There were 8 warnings in `mutate()`.
The first warning was:
ℹ In argument: `egfr0 = parse_number(ff_egfr_0)`.
Caused by warning:
! 2 parsing failures.
 row col expected actual
1276  -- a number    N/A
1336  -- a number    N/A
ℹ Run `dplyr::last_dplyr_warnings()` to see the 7 remaining warnings.
Show the code
df_pings2_bp <- 
    df_pings2_bp %>% 
    labelled::set_variable_labels(
            female = "Gender, female",
            d_st_type = "Type of Stroke",
            nihss_scale ="Stroke Severity (NIHSS)",
            ranking = "Modified Ranking Score",
            dm = "Diabetes Mellitus",
            sbp = "Systolic Blood Pressure",
            dbp = "Diastolic Blood Pressure",
            hpt = "Hypertesion",
            hyperlipidemia = "Hyperlipidemia", 
            tobacco_use = "Cigarette smoking", 
            obese_overwgt  = "Overweight & obesity",
            alcohol_curr = "Alcohol use, current", 
            acei = "ACE-Inhibitors",
            arb = "ARB",
            bb = "B-blockers",
            ccb = "Calcium channel blocker",
            diuretics = "Diuretics", 
            female = "Gender, female",
            income2 = "Income level", 
            educ2 = "Educational Level",
            agecat = "Age in years",
            h_alpha_md = "Alpha Methyl Dopa",
            h_alpha_ab = "Alpha Adrenergic Blockers",
            h_antiplt = "Antiplatelets",
            h_statins = "Statins",
            morisky_4_item = "Morisky (4 Items)",
            hillbone = "Total Hillbone Score",
            aa_hkq = "Health Literacy in HPT/stroke",
            eq_5d = "Health Related QoL",
            p_health = "Health Related QoL", 
            hpt_self_care = "Hypertension Self Care", 
            sbp_less_140_itt = "SBP < 140 mmHg at month 12 (ITT)",
            sbp_less_140_pp = "SBP < 140 mmHg at month 12 (PP)", 
            bp_less_140_90_itt = "BP < 140/90 mmHg at month 12 (ITT)", 
            bp_less_140_90_pp = "BP < 140/90 mmHg at month 12 (PP)",
            sbp_diff = "Change in SBP(month 12 from baseline - PP)",
            dbp_diff = "Change in DBP(month 12 from baseline - PP)",
            sbp_less_130_itt = "SBP < 130 mmHg at month 12 (ITT)",
            sbp_less_130_pp = "SBP < 130 mmHg at month 12 (PP)",
            sbp_less_135_itt = "SBP < 135 mmHg at month 12 (ITT)",
            sbp_less_135_pp = "SBP < 135 mmHg at month 12 (PP)",
            max_review = "Follow-up period",
            review_no = "Review number",
            completed_study = "Completed Study",
            sbp_2 = "Systolic Blood Pressure (ITT)", 
            dbp_2 = "Systolic Blood Pressure (ITT)", 
            sbp_baseline = "Systolic Blood Pressure (Baseline)",
            dbp_baseline = "Diastolic Blood Pressure (Baseline)",
            sbp_diff_itt ="Change in SBP(month 12 from baseline)- ITT",
            dbp_diff_itt = "Change in DBP(month 12 from baseline) - ITT")

df_drugs_class_raw <- 
  readxl::read_xlsx(
      "drugs_data_clean_10122025.xlsx", sheet = 1) %>% 
    filter(!is.na(hpt_drug_class) & eventname == "Baseline")

df_drugs_class <- 
  readxl::read_xlsx(
      "drugs_data_clean_10122025.xlsx", sheet = 1) %>% 
    filter(!is.na(hpt_drug_class) & eventname == "Baseline") %>% 
    select(pid, hpt_drug_class, antihpt) %>% 
    pivot_wider(
        id_cols = pid, 
        names_from = hpt_drug_class, 
        values_from = antihpt) %>% 
    unnest(-pid) %>% 
    slice(-15) %>%
    mutate(across(BB:`ALPHA BLOCKER`, ~ifelse(is.na(.x), 0, .x))) %>% 
    arrange(pid) %>% 
    distinct()
Warning: Values from `antihpt` are not uniquely identified; output will contain
list-cols.
• Use `values_fn = list` to suppress this warning.
• Use `values_fn = {summary_fun}` to summarise duplicates.
• Use the following dplyr code to identify duplicates.
  {data} |>
  dplyr::summarise(n = dplyr::n(), .by = c(pid, hpt_drug_class)) |>
  dplyr::filter(n > 1L)
Show the code
df_max_drug_doses_temp <- 
  readxl::read_xlsx(
      "PINGS_Antihypertensive Maximum doses.xlsx", sheet = 2)

df_pings_cox <- 
    readxl::read_xlsx(
      "PINGS_MACE and Participant follow-up review1.xlsx", 
      sheet = 2) %>% 
    janitor::clean_names() %>% 
    rename(
        outc_all_cause = all_cause_death, 
        dura_outc = duration_of_follow_up,
        mace = mace_1_0,
        dura_mace = time_to_event) %>% 
    mutate(
        participant_id_2 = sub("-(\\d)$", "-0\\1", participant_id_2), 
        pid = participant_id_2, 
        mace = case_when(is.na(mace) ~ 0, TRUE ~ mace),
        dura_outc = case_when(
            dura_outc > 380 ~ 380, TRUE ~ dura_outc),
        dura_mace = case_when(
            is.na(dura_mace) ~ dura_outc, 
            dura_mace > dura_outc ~ dura_outc, 
            TRUE ~ dura_mace), 
        dura_mace = case_when(dura_mace > 380 ~ 380, TRUE ~ dura_mace), 
        allocation_4 = factor(
          allocation_4, 
          levels = c("Arm 2- Routine Care", "Arm 1- Intervention Arm"), 
          labels = c("Routine", "Intervention")), 
        mace_2 = factor(
            mace, 
            levels = c(0, 1), 
            label = c("No", "Yes"))) %>%
    select(
        -c(serial_number, study_site_3, 
           vital_status_alive_0_dead_1_lost_2, 
           enrollment_date_5, 
           date_of_last_study_visit, 
           participant_id_9, study_site_10, 
           allocation_11,event_date,
           enrollment_date_13, x19)) 
New names:
• `PARTICIPANT ID` -> `PARTICIPANT ID...2`
• `STUDY SITE` -> `STUDY SITE...3`
• `ALLOCATION` -> `ALLOCATION...4`
• `ENROLLMENT DATE` -> `ENROLLMENT DATE...5`
• `PARTICIPANT ID` -> `PARTICIPANT ID...9`
• `STUDY SITE` -> `STUDY SITE...10`
• `ALLOCATION` -> `ALLOCATION...11`
• `ENROLLMENT DATE` -> `ENROLLMENT DATE...13`
• `` -> `...19`
Show the code
df_drugs <-
    df_drugs_class_raw %>%
    left_join(df_max_drug_doses_temp, by = "drug") %>%
    mutate(
        dose_index = freq_number*dose_number/maxi,
        antihpt  = case_when(is.na(antihpt) ~ 0, TRUE ~ antihpt)) %>%
    filter(antihpt == 1) %>%
    group_by(pid, eventname, arm) %>%
    summarize(
      n_hpts = sum(antihpt),
      dose_index = sum(dose_index)) %>%
    ungroup() %>%
    filter(eventname == "Baseline")
`summarise()` has grouped output by 'pid', 'eventname'. You can override using
the `.groups` argument.
Show the code
df_for_mace_paper <- 
    df_pings2_bp %>%  # labelled::look_for("statin")
    filter(eventname %in%  c("Baseline","Month12")) %>% 
    group_by(pid) %>%
    mutate(completed_study = any(!is.na(sbp) & eventname == "Month12")) %>%
    ungroup() %>%
    filter(eventname == "Baseline") %>%
    full_join(df_pings_cox) %>%
    full_join(df_drugs_class) %>% 
    full_join(df_drugs) %>% 
    filter(!(!completed_study & mace_2 == "No")) %>%
    mutate(across(BB:`ALPHA BLOCKER`, ~ifelse(is.na(.x), 0, .x))) %>% 
    select(
        mace, mace_2,  a_agebase, a_gender, educ, a_maristat, a_domicile,  
        a_income, a_religion, d_st_type, d_st_type_2, nihss_scale, ranking, 
        hyperlipidemia, hpt, sbp_gr_eq_160_baseline, dm, tobacco_use,
        obese_overwgt, bmi_cat, ff_hba1c_0, hba1c_high, sbp, dbp, 
        BB:`ALPHA BLOCKER`, dose_index, h_antiplt, h_statins, 
        hillbone, aa_hkq, arm, dura_mace) 
Joining with `by = join_by(pid)`
Joining with `by = join_by(pid)`
Joining with `by = join_by(pid, eventname, arm)`

Table 1

Show the code
gtsummary::reset_gtsummary_theme()
gtsummary::theme_gtsummary_compact()
Setting theme "Compact"
Show the code
df_for_mace_paper %>%
    select(-mace) %>% 
    gtsummary::tbl_summary(by = mace_2) %>% 
    gtsummary::add_overall(last = T) %>% 
    gtsummary::bold_labels() %>% 
    gtsummary::add_p() %>% 
    gtsummary::bold_p()
Characteristic No
N = 3951
Yes
N = 241
Overall
N = 4191
p-value2
Age in years 57 (50, 66) 64 (52, 70) 57 (50, 66) 0.11
Gender


0.9
    Male 223 (56%) 14 (58%) 237 (57%)
    Female 172 (44%) 10 (42%) 182 (43%)
Level of Formal education


0.2
    None 36 (9.1%) 3 (13%) 39 (9.3%)
    Primary 163 (41%) 5 (21%) 168 (40%)
    Secondary 126 (32%) 11 (46%) 137 (33%)
    Tertiary 70 (18%) 5 (21%) 75 (18%)
Marital Status


0.7
    Never Married 20 (5.1%) 1 (4.2%) 21 (5.0%)
    Currently Married 260 (66%) 17 (71%) 277 (66%)
    Separated 28 (7.1%) 2 (8.3%) 30 (7.2%)
    Widow/Widower 64 (16%) 3 (13%) 67 (16%)
    Cohabitating 6 (1.5%) 1 (4.2%) 7 (1.7%)
    Divorced 17 (4.3%) 0 (0%) 17 (4.1%)
Domicile


0.5
    Rural 25 (6.3%) 2 (8.3%) 27 (6.4%)
    Semi-Urban 129 (33%) 10 (42%) 139 (33%)
    Urban 241 (61%) 12 (50%) 253 (60%)
Income Bracket


0.5
    0-100 135 (34%) 8 (33%) 143 (34%)
    101-250 120 (31%) 7 (29%) 127 (30%)
    251-500 87 (22%) 8 (33%) 95 (23%)
    501-1500 34 (8.7%) 0 (0%) 34 (8.2%)
    1501-3000 12 (3.1%) 1 (4.2%) 13 (3.1%)
    > 3000 5 (1.3%) 0 (0%) 5 (1.2%)
    Unknown 2 0 2
Religion


0.2
    Christianity 356 (90%) 19 (79%) 375 (89%)
    Islam 37 (9.4%) 5 (21%) 42 (10%)
    Other 2 (0.5%) 0 (0%) 2 (0.5%)
Type of Stroke


0.7
    Ischemic Stroke 272 (74%) 18 (86%) 290 (75%)
    Intracerebral Hemorrhagic Stroke 85 (23%) 3 (14%) 88 (23%)
    Ischemic With Hemorrhagic Transformation 7 (1.9%) 0 (0%) 7 (1.8%)
    Untyped Stroke (no CT scan available) 4 (1.1%) 0 (0%) 4 (1.0%)
    Unknown 27 3 30
d_st_type_2


0.5
    Ischemic Stroke 279 (76%) 18 (86%) 297 (76%)
    Intracerebral Hemorrhagic Stroke 85 (23%) 3 (14%) 88 (23%)
    Untyped Stroke (no CT scan available) 4 (1.1%) 0 (0%) 4 (1.0%)
    Unknown 27 3 30
Stroke Severity (NIHSS) 2.0 (0.0, 7.0) 7.5 (0.0, 13.5) 2.0 (0.0, 7.0) 0.013
    Unknown 6 0 6
Modified Ranking Score


0.015
    0 29 (7.3%) 4 (17%) 33 (7.9%)
    1 93 (24%) 3 (13%) 96 (23%)
    2 124 (31%) 3 (13%) 127 (30%)
    3 79 (20%) 6 (25%) 85 (20%)
    4 69 (17%) 7 (29%) 76 (18%)
    5 1 (0.3%) 1 (4.2%) 2 (0.5%)
Hyperlipidemia 135 (34%) 5 (21%) 140 (33%) 0.2
Hypertesion 369 (93%) 24 (100%) 393 (94%) 0.4
sbp_gr_eq_160_baseline


0.14
    <160mmHg 256 (65%) 12 (50%) 268 (64%)
    >=160mmHg 139 (35%) 12 (50%) 151 (36%)
Diabetes Mellitus 133 (34%) 9 (38%) 142 (34%) 0.7
Cigarette smoking 27 (7.0%) 6 (25%) 33 (8.1%) 0.008
    Unknown 10 0 10
Overweight & obesity 207 (59%) 16 (80%) 223 (60%) 0.064
    Unknown 45 4 49
bmi_cat


0.2
    Normal 143 (41%) 4 (20%) 147 (40%)
    Overweight 109 (31%) 9 (45%) 118 (32%)
    Obese 98 (28%) 7 (35%) 105 (28%)
    Unknown 45 4 49
HBA1C (Baseline) 5.80 (5.40, 6.70) 6.30 (5.65, 9.25) 5.90 (5.40, 6.70) 0.13
    Unknown 82 4 86
hba1c_high 93 (30%) 8 (40%) 101 (30%) 0.3
    Unknown 82 4 86
Systolic Blood Pressure 154 (146, 168) 158 (147, 175) 154 (146, 169) 0.3
Diastolic Blood Pressure 94 (87, 101) 95 (85, 106) 94 (87, 101) 0.7
BB 58 (15%) 4 (17%) 62 (15%) 0.8
CCB 328 (83%) 19 (79%) 347 (83%) 0.6
ARB 217 (55%) 9 (38%) 226 (54%) 0.10
DIURETIC 112 (28%) 8 (33%) 120 (29%) 0.6
METHYLDOPA 32 (8.1%) 2 (8.3%) 34 (8.1%) >0.9
ACEI 70 (18%) 8 (33%) 78 (19%) 0.10
VASODILATOR 34 (8.6%) 1 (4.2%) 35 (8.4%) 0.7
ALPHA BLOCKER 1 (0.3%) 0 (0%) 1 (0.2%) >0.9
dose_index 1.46 (0.83, 1.92) 1.33 (0.83, 1.75) 1.46 (0.83, 1.92) 0.5
    Unknown 43 3 46
Antiplatelets 234 (63%) 17 (85%) 251 (64%) 0.048
    Unknown 25 4 29
Statins 288 (77%) 16 (80%) 304 (78%) >0.9
    Unknown 23 4 27
Total Hillbone Score 53.0 (50.0, 53.0) 51.0 (46.0, 53.0) 52.0 (50.0, 53.0) 0.065
    Unknown 6 1 7
Health Literacy in HPT/stroke 9 (7, 10) 7 (3, 9) 9 (6, 10) 0.12
    Unknown 21 1 22
arm


0.8
    Intervention 191 (48%) 11 (46%) 202 (48%)
    Routine 204 (52%) 13 (54%) 217 (52%)
dura_mace 362 (336, 370) 106 (42, 295) 357 (336, 370) <0.001
1 Median (Q1, Q3); n (%)
2 Wilcoxon rank sum test; Pearson’s Chi-squared test; Fisher’s exact test

Table II

Show the code
surv_obj <- 
    survival::Surv(
        time = df_for_mace_paper$dura_mace, 
        event = df_for_mace_paper$mace)


tbl_cox_uv <- 
    df_for_mace_paper %>% 
    select(-c(mace_2, mace)) %>% 
    gtsummary::tbl_uvregression(
        y = surv_obj,
        method = survival::coxph,
        exponentiate = TRUE) %>% 
    gtsummary::bold_labels() %>% 
    gtsummary::bold_p()
Warning: Using an external vector in selections was deprecated in tidyselect 1.1.0.
ℹ Please use `all_of()` or `any_of()` instead.
  # Was:
  data %>% select(surv_obj)

  # Now:
  data %>% select(all_of(surv_obj))

See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
There was a warning constructing the model for variable "a_maristat". See
message below.
! Loglik converged before variable 5 ; coefficient may be infinite.
There was a warning constructing the model for variable "a_income". See message
below.
! Loglik converged before variable 3,5 ; coefficient may be infinite.
There was a warning constructing the model for variable "a_religion". See
message below.
! Loglik converged before variable 2 ; coefficient may be infinite.
There was a warning constructing the model for variable "d_st_type". See
message below.
! Loglik converged before variable 2,3 ; coefficient may be infinite.
There was a warning constructing the model for variable "d_st_type_2". See
message below.
! Loglik converged before variable 2 ; coefficient may be infinite.
There was a warning constructing the model for variable "hpt". See message
below.
! Loglik converged before variable 1 ; coefficient may be infinite.
There was a warning constructing the model for variable "ALPHA BLOCKER". See
message below.
! Loglik converged before variable 1 ; coefficient may be infinite.
Show the code
tbl_cox_mv <- 
    df_for_mace_paper %>% 
    select(
        a_agebase, a_gender, a_religion, nihss_scale, tobacco_use, 
        ff_hba1c_0, h_antiplt, hillbone, aa_hkq) %>% 
    survival::coxph(
        surv_obj ~ ., data = .) %>% 
    gtsummary::tbl_regression(
        exponentiate = TRUE) %>%
    gtsummary::add_global_p() %>%
    gtsummary::bold_labels() %>% 
    gtsummary::bold_p()
Warning in coxph.fit(X, Y, istrat, offset, init, control, weights = weights, :
Loglik converged before variable 4 ; coefficient may be infinite.
Show the code
tbl_cox_uv   
Characteristic N HR 95% CI p-value
Age in years 419 1.03 0.99, 1.07 0.11
Gender 419


    Male

    Female
0.94 0.42, 2.12 0.9
Level of Formal education 419


    None

    Primary
0.41 0.10, 1.71 0.2
    Secondary
0.99 0.27, 3.54 >0.9
    Tertiary
0.91 0.22, 3.80 0.9
Marital Status 419


    Never Married

    Currently Married
1.29 0.17, 9.67 0.8
    Separated
1.28 0.12, 14.2 0.8
    Widow/Widower
0.93 0.10, 8.99 >0.9
    Cohabitating
3.12 0.19, 49.9 0.4
    Divorced
0.00 0.00, Inf >0.9
Domicile 419


    Rural

    Semi-Urban
1.10 0.24, 5.08 0.9
    Urban
0.63 0.14, 2.82 0.5
Income Bracket 417


    0-100

    101-250
0.92 0.33, 2.54 0.9
    251-500
1.57 0.59, 4.19 0.4
    501-1500
0.00 0.00, Inf >0.9
    1501-3000
1.15 0.14, 9.31 0.9
    > 3000
0.00 0.00, Inf >0.9
Religion 419


    Christianity

    Islam
2.43 0.91, 6.51 0.077
    Other
0.00 0.00, Inf >0.9
Type of Stroke 389


    Ischemic Stroke

    Intracerebral Hemorrhagic Stroke
0.51 0.15, 1.74 0.3
    Ischemic With Hemorrhagic Transformation
0.00 0.00, Inf >0.9
    Untyped Stroke (no CT scan available)
0.00 0.00, Inf >0.9
d_st_type_2 389


    Ischemic Stroke

    Intracerebral Hemorrhagic Stroke
0.52 0.15, 1.78 0.3
    Untyped Stroke (no CT scan available)
0.00 0.00, Inf >0.9
Stroke Severity (NIHSS) 413 1.14 1.07, 1.21 <0.001
Modified Ranking Score 419 1.31 0.93, 1.83 0.12
Hyperlipidemia 419


    No

    Yes
0.50 0.19, 1.34 0.2
Hypertesion 419


    No

    Yes
26,733,738 0.00, Inf >0.9
sbp_gr_eq_160_baseline 419


    <160mmHg

    >=160mmHg
1.82 0.82, 4.05 0.14
Diabetes Mellitus 419


    No

    Yes
1.23 0.54, 2.80 0.6
Cigarette smoking 409


    No

    Yes
4.00 1.59, 10.1 0.003
Overweight & obesity 370


    No

    Yes
2.63 0.88, 7.88 0.084
bmi_cat 370


    Normal

    Overweight
2.81 0.87, 9.13 0.085
    Obese
2.43 0.71, 8.31 0.2
HBA1C (Baseline) 333 1.16 0.99, 1.35 0.060
hba1c_high 333


    No

    Yes
1.57 0.64, 3.84 0.3
Systolic Blood Pressure 419 1.01 1.00, 1.03 0.14
Diastolic Blood Pressure 419 1.00 0.97, 1.03 >0.9
BB 419 1.25 0.43, 3.66 0.7
CCB 419 0.87 0.32, 2.32 0.8
ARB 419 0.60 0.26, 1.39 0.2
DIURETIC 419 1.34 0.57, 3.15 0.5
METHYLDOPA 419 1.06 0.25, 4.53 >0.9
ACEI 419 1.82 0.77, 4.31 0.2
VASODILATOR 419 0.57 0.08, 4.25 0.6
ALPHA BLOCKER 419 0.00 0.00, Inf >0.9
dose_index 373 0.80 0.44, 1.47 0.5
Antiplatelets 390


    FALSE

    TRUE
3.30 0.97, 11.3 0.057
Statins 392


    FALSE

    TRUE
1.16 0.39, 3.48 0.8
Total Hillbone Score 412 0.90 0.83, 0.97 0.005
Health Literacy in HPT/stroke 397 0.88 0.78, 1.00 0.050
arm 419


    Intervention

    Routine
1.17 0.53, 2.62 0.7
dura_mace 419


Abbreviations: CI = Confidence Interval, HR = Hazard Ratio
Show the code
tbl_cox_mv 
Characteristic HR 95% CI p-value
Age in years 1.02 0.97, 1.08 0.4
Gender

0.4
    Male
    Female 0.60 0.18, 2.02
Religion

0.4
    Christianity
    Islam 2.41 0.62, 9.33
    Other 0.00 0.00, Inf
Stroke Severity (NIHSS) 1.11 1.03, 1.21 0.006
Cigarette smoking

0.2
    No
    Yes 2.66 0.66, 10.7
HBA1C (Baseline) 1.07 0.86, 1.34 0.5
Antiplatelets

0.3
    FALSE
    TRUE 2.07 0.56, 7.73
Total Hillbone Score 0.91 0.79, 1.04 0.2
Health Literacy in HPT/stroke 0.95 0.80, 1.12 0.5
Abbreviations: CI = Confidence Interval, HR = Hazard Ratio

Table 3