## ----setup, include=FALSE----------------------------------------------------- knitr::opts_chunk$set(echo = TRUE) library(tibble) library(kableExtra) library(checkmate) ## ----new_classes, echo=FALSE-------------------------------------------------- new_classes <- tribble( ~category, ~class_new_name, ~comment, "Parent model class", "ModelParamsNormal", "Represents parameters of bivariate normal distribution.", "Model", "OneParLogNormalPrior", "standard CRM with a normal prior on the log power parameter for the skeleton prior probabilities", "Design", "DADesign", "Design for data augmentation.", "Model", "DALogisticLogNormal", "Logistic model with bivariate (log) normal prior and data augmentation.", "Data", "DataDA", "Time-to-DLT augmented data.", "Model", "FractionalCRM", "Fractional CRM model.", "Increments", "IncrementsHSRBeta", "Limiting further increments using a Hard Safety Rule", "Increments", "IncrementsRelativeDLTCurrent", "Increments control based on relative differences in terms of DLTs.", "nextBest", "NextBestEWOC", "Next best dose is the highest possible dose subject to overdose control.", "nextBest", "NextBestInfTheory", "Next best dose that is based on information theory.", "nextBest", "NextBestMinDist", "Next best dose that is based on minimum distance to target probability.", "nextBest", "NextBestNCRMLoss", "Next best dose based on NCRM rule and loss function.", "nextBest", "NextBestProbMTDLTE", paste( "Next best dose that selects the dose with the highest probability of having a toxicity", "rate less or equal to the toxicity target." ), "nextBest", "NextBestProbMTDMinDist", paste( " Next best dose that selects the dose with the highest probability of having a toxicity", "rate with the smallest distance to the toxicity target." ), "Model", "OneParExpPrior", "Standard CRM with an exponential prior on the power parameter.", "Model", "ProbitLogNormalRel", "Probit regression model with a bivariate normal prior on the intercept and log slope.", "SafetyWindow", "SafetyWindowConst", "Safety window length used when the `gap` should be kept constant.", "SafetyWindow", "SafetyWindowSize", "Safety window length based on cohort size.", "Stopping", "StoppingLowestDoseHSRBeta", "Stopping based on a Hard Safety Rule using the Beta posterior distribution.", "Stopping", "StoppingMTDCV", "Stopping rule based on precision of MTD which is calculated as the coefficient of variation (CV) of the MTD.", "Stopping", "StoppingMissingDose", "Stopping based on NA returned by next best dose.", "Stopping", "StoppingSpecificDose", "Testing a stopping rule at specific dose of the dose grid and not at the next best dose." ) ## ----new_classes_kbl, echo=FALSE, results='markup'---------------------------- cn <- new_classes cn <- cn[order(cn$category, cn$class_new_name), ] kbl(cn, longtable = TRUE, booktabs = TRUE, col.names = NULL, escape = FALSE) %>% add_header_above(c("Category", "Name", "Comment")) %>% column_spec(1:3, width = "6cm", border_left = TRUE, border_right = TRUE) %>% kable_styling(latex_options = c("repeat_header"), font_size = 11) ## ----renamed_classes, echo=FALSE---------------------------------------------- renamed_classes <- tribble( ~category, ~class_new_name, ~class_old_name, ~comment, "Increments", "IncrementsDoseLevels", "IncrementsNumDoseLevels", "Harmonization", "Increments", "IncrementsMin", "IncrementMin", "Harmonization", "Stopping", "StoppingMaxGainCIRatio", "StoppingGstarCIRatio", "Clarification" ) ## ----renamed_classes_kbl, echo=FALSE, results='markup'------------------------ cr <- renamed_classes cr <- cr[order(cr$category, cr$class_new_name), ] kbl(cr, longtable = TRUE, booktabs = TRUE, col.names = NULL, escape = FALSE) %>% add_header_above(c("Category", "New Name", "Old Name", "Reason")) %>% column_spec(1:4, width = "6cm", border_left = TRUE, border_right = TRUE) %>% kable_styling(latex_options = c("repeat_header"), font_size = 11) ## ----renamed_slots, echo=FALSE------------------------------------------------ # "helper", "positive_number", "", "", FALSE, "to handle strictly positive valued slots # (e.g. `ref_dose` in many model classes)", # "OneParLogNormalPrior", "", "", "skel_fun", FALSE, "", # "OneParLogNormalPrior", "", "", "skel_fun_inv", FALSE, "", # "OneParLogNormalPrior", "", "", "skel_probs", FALSE, "", # "OneParLogNormalPrior()", "", "", "dose_grid", FALSE, "", # "Model", "ModelLogNormal", "", # "Parent model class", "ModelLogNormal", "new parent class for all the models with reference dose and # bivariate (log) normal prior on the model parameters", class_changes <- tribble( ~class_name, ~slot_name, ~slot_new_name, ~was_removed, ~comment, "ModelEff", "dose", "", TRUE, "moved to model class method", "ModelEff", "ExpEff", "", TRUE, "moved to model class method and renamed to `efficacy`", "Effloglog", "several slots", "several slots", FALSE, "several slot changed, see man page", "EffFlexi", "several slots", "several slots", FALSE, "several slot changed, see man page", "EffFlexi()", "smooth", "", TRUE, "replaced by `rw1` flag", "EffFlexi()", "rw1", "", FALSE, "replaces `smooth` string", "DALogisticLogNormal", "C_par", "c_par", FALSE, "", "DALogisticLogNormal", "conditionalPEM", "cond_pem", FALSE, "", "TITELogisticLogNormal", "weightMethod", "weight_method", FALSE, "", "DualEndpointBeta", "refDoseBeta", "ref_dose_beta", FALSE, "", "DualEndpointEmax", "refDoseEmax", "ref_dose_emax", FALSE, "", "DualEndpointRW", "useRW1", "rw1", FALSE, "", "DualEndpointRW()", "smooth", "", TRUE, "replaced by `rw1` flag", "DualEndpointRW()", "", "rw1", FALSE, "replaces `smooth` string", "McmcOptions", "", "rng_kind", FALSE, "to be used by Random Number Generator in rJAGS", "McmcOptions", "", "rng_seed", FALSE, "to be used by Random Number Generator in rJAGS", "NextBestTD", "targetDuringTrial", "prob_target_drt", FALSE, "", "NextBestTD", "targetEndOfTrial", "prob_target_eot", FALSE, "", "NextBestTDsamples", "targetDuringTrial", "prob_target_drt", FALSE, "", "NextBestTDsamples", "targetEndOfTrial", "prob_target_eot", FALSE, "", "NextBestNCRM", "maxOverdoseProb", "max_overdose_prob", FALSE, "", "NextBestDualEndpoint", "scale", "", TRUE, "replaced by `target_relative` flag", "NextBestDualEndpoint", "", "target_relative", FALSE, "replaces `scale` string", "NextBestDualEndpoint", "maxOverdoseProb", "max_overdose_prob", FALSE, "", "NextBestDualEndpoint", "targetThresh", "target_thresh", FALSE, "", "NextBestMaxGain", "DLEDuringTrialtarget", "prob_target_drt", FALSE, "", "NextBestMaxGain", "DLEEndOfTrialtarget", "prob_target_eot", FALSE, "", "NextBestMaxGainSamples", "DLEDuringTrialtarget", "prob_target_drt", FALSE, "", "NextBestMaxGainSamples", "DLEEndOfTrialtarget", "prob_target_eot", FALSE, "", "NextBestMaxGainSamples", "TDderive", "derive", FALSE, "", "NextBestMaxGainSamples", "Gstarderive", "mg_derive", FALSE, "", "IncrementsRelativeParts", "dltStart", "dlt_start", FALSE, "", "IncrementsRelativeParts", "cleanStart", "clean_start", FALSE, "change applied also to other dependent classes", "IncrementsRelativeDLT", "DLTintervals", "dlt_intervals", FALSE, "change applied also to other dependent classes", "IncrementsDoseLevels (IncrementsNumDoseLevels)", "maxLevels", "levels", FALSE, "change applied also to other dependent classes", "IncrementsDoseLevels (IncrementsNumDoseLevels)", "", "basis_level", FALSE, "", "IncrementsMin (IncrementMin)", "IncrementsList", "increments_list", FALSE, "change applied also to other dependent classes", "StoppingTargetBiomarker", "scale", "", TRUE, "replaced by `is_relative` flag", "StoppingTargetBiomarker", "", "is_relative", FALSE, "replaces `scale` string", "StoppingList", "stopList", "stop_list", FALSE, "", "StoppingAll", "stopList", "stop_list", FALSE, "", "StoppingAny", "stopList", "stop_list", FALSE, "", "StoppingTDCIRatio", "targetRatio", "target_ratio", FALSE, "", "StoppingTDCIRatio", "targetEndOfTrial", "prob_target", FALSE, "", "StoppingMaxGainCIRatio (StoppingGstarCIRatio)", "targetRatio", "target_ratio", FALSE, "", "StoppingMaxGainCIRatio (StoppingGstarCIRatio)", "targetEndOfTrial", "prob_target", FALSE, "", "CohortSizeRange", "cohortSize", "cohort_size", FALSE, "", "CohortSizeDLT", "DLTintervals", "dlt_intervals", FALSE, "", "CohortSizeDLT", "cohortSize", "cohort_size", FALSE, "", "CohortSizeMax", "cohortSizeList", "cohort_size_list", FALSE, "", "CohortSizeMin", "cohortSizeList", "cohort_size_list", FALSE, "", "Design", "PLcohortSize", "pl_cohort_size", FALSE, "", "TDsamplesDesign", "PLcohortSize", "pl_cohort_size", FALSE, "", "TDDesign", "PLcohortSize", "pl_cohort_size", FALSE, "" ) ## ----renamed_slots_kbl, echo=FALSE, results='markup'-------------------------- cc <- class_changes cc <- cc[order(cc$class_name, cc$slot_name, cc$slot_new_name), ] no_slot_change <- nchar(trimws(cc$slot_name)) == 0 cc$class_name <- cell_spec( cc$class_name, strikeout = ifelse(cc$was_removed & no_slot_change, TRUE, FALSE) ) cc$slot_name <- cell_spec( cc$slot_name, strikeout = ifelse(cc$was_removed & !no_slot_change, TRUE, FALSE) ) cc <- cc[, -4] kbl(cc, longtable = TRUE, booktabs = TRUE, col.names = NULL, escape = FALSE) %>% add_header_above(c("Name", "Name", "New Name", "")) %>% add_header_above(c("Class/Constructor[note]" = 1, "Slot/Arg[note]" = 2, "Comment")) %>% column_spec(1:4, width = "6cm", border_left = TRUE, border_right = TRUE) %>% collapse_rows(columns = 1, valign = "top") %>% kable_styling(latex_options = c("repeat_header"), font_size = 11) %>% add_footnote( c( "Class or class' user constructor. In the later case the Name/New Name is followed by ().", "Slot in case of the class or argument in case of the class' user constructor" ), notation = "symbol" ) ## ----data_model_samples------------------------------------------------------- library(crmPack) empty_data <- Data(doseGrid = c(1, 3, 5, 10, 15, 20, 25, 40, 50, 80, 100)) my_model <- LogisticNormal( mean = c(-0.85, 1), cov = matrix(c(1, -0.5, -0.5, 1), nrow = 2) ) my_options <- McmcOptions(burnin = 2, step = 2, samples = 20) my_samples <- mcmc(empty_data, my_model, my_options) ## ----dose_function------------------------------------------------------------ # Doses reaching a specific target probability of the occurrence of a DLT (equal to 0.3), # given a particular models and samples. # Every single dose corresponds to one particular sample in `my_samples`. dose(0.3, my_model, my_samples) # True dose-DLT relationship. # Say that -0.8 and 1 are the true values for models parameters alpha0 and alpha1 respectively. # The `true_dose_fun` takes one argument (target probability of the occurrence of a DLT) # and computes the corresponding dose, according to the model chosen and given a fixed values # of the model's parameters. true_dose_fun <- doseFunction(my_model, alpha0 = -0.8, alpha1 = 1) true_dose_fun(0.3) ## ----prob_function------------------------------------------------------------ # Toxicity probabilities for a given dose (equal to 10), model and samples. # Every single probability value corresponds to one particular sample in `my_samples`. prob(10, my_model, my_samples) # True DLT-dose relationship. # Say that -0.8 and 1 are the true values for models parameters alpha0 and alpha1 respectively. # The `true_prob_fun` takes one argument (the dose) and computes the corresponding # toxicity probability, according to the model chosen and given a fixed values # of the model's parameters. true_prob_fun <- probFunction(my_model, alpha0 = -0.8, alpha1 = 1) true_prob_fun(10) ## ----------------------------------------------------------------------------- .DefaultStoppingAll() class_name <- "LogisticNormal" eval(parse(text = paste0(".Default", class_name, "()"))) ## ----class_changes, echo=FALSE------------------------------------------------ class_changes <- tribble( ~class_name, ~class_new_name, ~slot_name, ~slot_new_name, ~was_removed, ~comment, "", "positive_number", "", "", FALSE, "to handle strictly positive valued slots (e.g. `ref_dose` in many model classes)", "", "ModelLogNormal", "", "", FALSE, "new parent class for all the models with reference dose and bivariate (log) normal prior on the model parameters", "", "ModelParamsNormal", "", "", FALSE, "represents parameters of bivariate normal distribution", "AllModels", "", "", "", TRUE, "", "Model", "", "", "", TRUE, "", "GeneralModel", "", "", "datanames", FALSE, "moved from `AllModels`", "GeneralModel", "", "", "datanames_prior", FALSE, "", "ModelEff", "", "dose", "", TRUE, "moved to model class method", "ModelEff", "", "ExpEff", "", TRUE, "moved to model class method and renamed to `efficacy`", "Effloglog", "", "several slots", "several slots", FALSE, "several slot changed, see man page", "EffFlexi", "", "several slots", "several slots", FALSE, "several slot changed, see man page", "EffFlexi()", "", "smooth", "", TRUE, "replaced by `rw1` flag", "EffFlexi()", "", "", "rw1", FALSE, "replaces `smooth` string", "DALogisticLogNormal", "", "C_par", "c_par", FALSE, "", "DALogisticLogNormal", "", "conditionalPEM", "cond_pem", FALSE, "", "TITELogisticLogNormal", "", "weightMethod", "weight_method", FALSE, "", "OneParLogNormalPrior", "", "skeletonFun", "skel_fun", FALSE, "", "OneParLogNormalPrior", "", "", "skel_fun_inv", FALSE, "", "OneParLogNormalPrior", "", "skeletonProbs", "skel_probs", FALSE, "", "OneParLogNormalPrior()", "", "doseGrid", "dose_grid", FALSE, "", "DualEndpointBeta", "", "refDoseBeta", "ref_dose_beta", FALSE, "", "DualEndpointEmax", "", "refDoseEmax", "ref_dose_emax", FALSE, "", "DualEndpointRW", "", "useRW1", "rw1", FALSE, "", "DualEndpointRW()", "", "smooth", "", TRUE, "replaced by `rw1` flag", "DualEndpointRW()", "", "", "rw1", FALSE, "replaces `smooth` string", "McmcOptions", "", "", "rng_kind", FALSE, "to be used by Random Number Generator in rJAGS", "McmcOptions", "", "", "rng_seed", FALSE, "to be used by Random Number Generator in rJAGS", "NextBestTD", "", "targetDuringTrial", "prob_target_drt", FALSE, "", "NextBestTD", "", "targetEndOfTrial", "prob_target_eot", FALSE, "", "NextBestTDsamples", "", "targetDuringTrial", "prob_target_drt", FALSE, "", "NextBestTDsamples", "", "targetEndOfTrial", "prob_target_eot", FALSE, "", "NextBestNCRM", "", "maxOverdoseProb", "max_overdose_prob", FALSE, "", "NextBestDualEndpoint", "", "scale", "", TRUE, "replaced by `target_relative` flag", "NextBestDualEndpoint", "", "", "target_relative", FALSE, "replaces `scale` string", "NextBestDualEndpoint", "", "maxOverdoseProb", "max_overdose_prob", FALSE, "", "NextBestDualEndpoint", "", "targetThresh", "target_thresh", FALSE, "", "NextBestMaxGain", "", "DLEDuringTrialtarget", "prob_target_drt", FALSE, "", "NextBestMaxGain", "", "DLEEndOfTrialtarget", "prob_target_eot", FALSE, "", "NextBestMaxGainSamples", "", "DLEDuringTrialtarget", "prob_target_drt", FALSE, "", "NextBestMaxGainSamples", "", "DLEEndOfTrialtarget", "prob_target_eot", FALSE, "", "NextBestMaxGainSamples", "", "TDderive", "derive", FALSE, "", "NextBestMaxGainSamples", "", "Gstarderive", "mg_derive", FALSE, "", "IncrementsRelativeParts", "", "dltStart", "dlt_start", FALSE, "", "IncrementsRelativeParts", "", "cleanStart", "clean_start", FALSE, "change applied also to other dependent classes", "IncrementsRelativeDLT", "", "DLTintervals", "intervals", FALSE, "change applied also to other dependent classes", "IncrementsNumDoseLevels", "IncrementsDoseLevels", "", "", FALSE, "", "IncrementsDoseLevels", "", "maxLevels", "levels", FALSE, "change applied also to other dependent classes", "IncrementsDoseLevels", "", "", "basis_level", FALSE, "", "IncrementMin", "IncrementsMin", "", "", FALSE, "", "IncrementsMin", "", "IncrementsList", "increments_list", FALSE, "change applied also to other dependent classes", "StoppingTargetBiomarker", "", "scale", "", TRUE, "replaced by `is_relative` flag", "StoppingTargetBiomarker", "", "", "is_relative", FALSE, "replaces `scale` string", "StoppingList", "", "stopList", "stop_list", FALSE, "", "StoppingAll", "", "stopList", "stop_list", FALSE, "", "StoppingAny", "", "stopList", "stop_list", FALSE, "", "StoppingTDCIRatio", "", "targetRatio", "target_ratio", FALSE, "", "StoppingTDCIRatio", "", "targetEndOfTrial", "prob_target", FALSE, "", "StoppingGstarCIRatio", "", "targetRatio", "target_ratio", FALSE, "", "StoppingGstarCIRatio", "", "targetEndOfTrial", "prob_target", FALSE, "", "StoppingGstarCIRatio", "StoppingMaxGainCIRatio", "", "", FALSE, "", "CohortSizeRange", "", "cohortSize", "cohort_size", FALSE, "", "CohortSizeDLT", "", "DLTintervals", "intervals", FALSE, "", "CohortSizeDLT", "", "cohortSize", "cohort_size", FALSE, "", "CohortSizeMax", "", "cohortSizeList", "cohort_sizes", FALSE, "", "CohortSizeMin", "", "cohortSizeList", "cohort_sizes", FALSE, "", "SafetyWindowSize", "", "patientGap", "gap", FALSE, "", "SafetyWindowSize", "", "sizeIntervals", "size", FALSE, "", "SafetyWindowSize", "", "patientFollow", "follow", FALSE, "", "SafetyWindowSize", "", "patientFollowMin", "follow_min", FALSE, "", "SafetyWindowConst", "", "patientGap", "gap", FALSE, "", "SafetyWindowConst", "", "patientFollow", "follow", FALSE, "", "SafetyWindowConst", "", "patientFollowMin", "follow_min", FALSE, "", "OneParExpNormalPrior", "OneParLogNormalPrior", "", "", FALSE, "", "Design", "", "PLcohortSize", "pl_cohort_size", FALSE, "", "TDsamplesDesign", "", "PLcohortSize", "pl_cohort_size", FALSE, "", "TDDesign", "", "PLcohortSize", "pl_cohort_size", FALSE, "" ) ## ----class_changes_kbl, echo=FALSE, results='markup'-------------------------- cc <- class_changes cc <- cc[order(cc$class_name, cc$class_new_name, cc$slot_name, cc$slot_new_name), ] no_slot_change <- nchar(trimws(cc$slot_name)) == 0 cc$class_name <- cell_spec( cc$class_name, strikeout = ifelse(cc$was_removed & no_slot_change, TRUE, FALSE) ) cc$slot_name <- cell_spec( cc$slot_name, strikeout = ifelse(cc$was_removed & !no_slot_change, TRUE, FALSE) ) cc <- cc[, -5] kbl(cc, longtable = TRUE, booktabs = TRUE, col.names = NULL, escape = FALSE) %>% add_header_above(c("Name", "New Name", "Name", "New Name", "")) %>% add_header_above(c("Class/Constructor[note]" = 2, "Slot/Arg[note]" = 2, "Comment")) %>% column_spec(1:5, width = "6cm", border_left = TRUE, border_right = TRUE) %>% collapse_rows(columns = 1, valign = "top") %>% kable_styling(latex_options = c("repeat_header"), font_size = 11) %>% add_footnote( c( "Class or class' user constructor. In the later case the Name/New Name is followed by ().", "Slot in case of the class or argument in case of the class' user constructor" ), notation = "symbol" ) ## ----method_changes, echo=FALSE----------------------------------------------- method_changes <- tribble( ~method_name, ~method_new_name, ~arg_name, ~arg_new_name, ~was_removed, ~output_changes, ~comment, "update-Data", "", "newCohort", "new_cohort", FALSE, "", "", "update-Data", "", "", "check", FALSE, "", "", "update-DataParts", "", "", "check", FALSE, "", "", "update-DataDual", "", "", "check", FALSE, "", "", "update-DataDA", "", "", "check", FALSE, "", "", "getEff", "", "", "", FALSE, "renamed elements in the list returned", "", "mcmc", "", "fromPrior", "from_prior", FALSE, "", "", "mcmc", "", "program", "", TRUE, "", "", "mcmc", "", "verbose", "", TRUE, "", "", "", "doseFunction", "", "", FALSE, "", "returns dose computing function for a given model", "", "probFunction", "", "", FALSE, "", "returns probability computing function for a given model", "dose", "", "prob", "x", FALSE, "", "", "", "efficacy", "", "", FALSE, "", "new generic function", "biomLevel", "biomarker", "", "", FALSE, "", "changed generic and methods", "biomLevel", "", "dose", "", TRUE, "", "changed generic and methods", "biomLevel-DualEndpoint", "", "dose", "", TRUE, "", "", "biomLevel", "", "", "xLevel", FALSE, "", "added only for generic, reordered arguments for generic and methods", "gain", "", "several arguments", "several arguments", FALSE, "", "several arguments (generic and methods) changed, see man page", "", "update-ModelPseudo", "", "", FALSE, "", "", "update-LogisticIndepBeta", "", "", "", TRUE, "", "replaced by `update-ModelPseudo`", "update-Effloglog", "", "", "", TRUE, "", "replaced by `update-ModelPseudo`", "update-EffFlexi", "", "", "", TRUE, "", "replaced by `update-ModelPseudo`", "nextBest-NextBestTD", "", "Effmodel", "model_eff", FALSE, "", "", "nextBest-NextBestTD", "", "Effsamples", "samples_eff", FALSE, "", "", "nextBest-NextBestTD", "", "SIM", "in_sim", FALSE, "", "", "nextBest-NextBestTDsamples", "", "Effmodel", "model_eff", FALSE, "", "", "nextBest-NextBestTDsamples", "", "Effsamples", "samples_eff", FALSE, "", "", "nextBest-NextBestMaxGain", "", "Effmodel", "model_eff", FALSE, "", "", "nextBest-NextBestMaxGain", "", "Effsamples", "samples_eff", FALSE, "", "", "nextBest-NextBestMaxGain", "", "SIM", "in_sim", FALSE, "", "", "nextBest-NextBestMaxGain", "", "", "", FALSE, "renamed elements in the list returned", "", "nextBest-NextBestMaxGainSamples", "", "Effmodel", "model_eff", FALSE, "", "", "nextBest-NextBestMaxGainSamples", "", "Effsamples", "samples_eff", FALSE, "", "", "nextBest-NextBestMaxGainSamples", "", "SIM", "in_sim", FALSE, "", "", "nextBest-NextBestMaxGainSamples", "", "", "", FALSE, "renamed elements in the list returned", "", "size", "size", "", "check", FALSE, "", "" ) ## ----method_changes_kbl, echo=FALSE, results='markup'------------------------- mc <- method_changes mc <- mc[order(mc$method_name, mc$method_new_name, mc$arg_name, mc$arg_new_name), ] no_arg_change <- nchar(trimws(mc$arg_name)) == 0 mc$method_name <- cell_spec( mc$method_name, strikeout = ifelse(mc$was_removed & no_arg_change, TRUE, FALSE) ) mc$arg_name <- cell_spec( mc$arg_name, strikeout = ifelse(mc$was_removed & !no_arg_change, TRUE, FALSE) ) mc <- mc[, -5] kbl(mc, longtable = TRUE, booktabs = TRUE, col.names = NULL, escape = FALSE) %>% add_header_above(c("Name", "New Name", "Name", "New Name", "", "")) %>% add_header_above(c("Method" = 2, "Argument" = 2, "Output Changes", "Comment")) %>% column_spec(1:6, width = "6cm", border_left = TRUE, border_right = TRUE) %>% collapse_rows(columns = 1, valign = "top") %>% kable_styling(latex_options = c("repeat_header"), font_size = 11)