Title: | Survival Control Charts Estimation Software |
---|---|
Description: | Quality control charts for survival outcomes. Allows users to construct the Continuous Time Generalized Rapid Response CUSUM (CGR-CUSUM) <doi:10.1093/biostatistics/kxac041>, the Biswas & Kalbfleisch (2008) <doi:10.1002/sim.3216> CUSUM, the Bernoulli CUSUM and the risk-adjusted funnel plot for survival data <doi:10.1002/sim.1970>. These procedures can be used to monitor survival processes for a change in the failure rate. |
Authors: | Daniel Gomon [aut, cre] |
Maintainer: | Daniel Gomon <[email protected]> |
License: | GPL (>= 3) |
Version: | 1.1.0 |
Built: | 2025-02-14 05:12:51 UTC |
Source: | https://github.com/d-gomon/success |
In a Poisson point process, subjects arrive with exponentially
distributed inter-arrival times with rate . This function
can be used to estimate the parameter
.
arrival_rate(data)
arrival_rate(data)
data |
A
If the |
A (named) vector containing the estimated arrival rate in the data, or for each unit in the data.
Daniel Gomon
arrival_rate(surgerydat)
arrival_rate(surgerydat)
This function allows to estimate the Average Run Length (ARL)
of the risk-adjusted Bernoulli CUSUM (see bernoulli_cusum()
)
through a Markov Chain Approach (Brook & Evans(1972) & Steiner et al. (2000)) or
exploiting the relationship with the Sequential Probability Ratio Test (Kemp (1971)).
The function requires the specification of one of the following combinations of parameters
as arguments to the function:
glmmod
& theta
p0
& theta
p0
& p1
Average run length of lower-sided Bernoulli CUSUM charts can be determined
by specifying theta
< 0.
bernoulli_ARL(h, n_grid, glmmod, theta, theta_true, p0, p1, method = c("MC", "SPRT"), smooth_prob = FALSE)
bernoulli_ARL(h, n_grid, glmmod, theta, theta_true, p0, p1, method = c("MC", "SPRT"), smooth_prob = FALSE)
h |
Control limit for the Bernoulli CUSUM |
n_grid |
Number of state spaces used to discretize the outcome space (when |
glmmod |
Generalized linear regression model used for risk-adjustment as produced by
the function
|
theta |
The
|
theta_true |
The true log odds ratio |
p0 |
The baseline failure probability at |
p1 |
The alternative hypothesis failure probability at |
method |
The method used to obtain the average run length. Either "MC" for Markov Chain or "SPRT" for SPRT methodology. Default = "MC". |
smooth_prob |
Should the probability distribution of failure under the null distribution be smoothed?
Useful for small samples. Can only be TRUE when |
The average run length of a CUSUM chart is given by
where
is defined as:
When method = "MC"
, the average run length will be determined by
the Markov Chain approach described
in Brook & Evans (1972), using the risk-adjustment correction proposed in
Steiner et al. (2000). The idea is to discretize the domain (0, h) into
state spaces, with
of width
and
of width
, such that
is an absorbing state. This is done using the following steps:
is determined using the relationship
.
Transition probabilities between the states are determined and
'transition matrix' is constructed.
The equation is
solved to find the ARL starting from each of the states.
When method = "SPRT"
, the average run length will be determined by
the relationship between the SPRT and CUSUM described in Kemp (1971), using the risk-adjustment
correction proposed in Steiner et al. (2000).
If N is the run length of a SPRT, P(0) the probability of
a SPRT terminating on the lower boundary of zero and R the run length of
a CUSUM, then:
and
are completely determined by
with the cdf of the singletons
. The integral can be
approximated using the generalized trapezoidal quadrature rule:
A list containing:
ARL_0
: A numeric value indicating the average run length in
number of outcomes when starting from state E_0.
ARL
: A data.frame
containing the average run length (#outcomes)
depending on the state in which the process starts
start_val
:Starting value of the CUSUM, corresponding to the
discretized state spaces ;
#outcomes
:ARL for the CUSUM with
initial value start_val
;
R
: A transition probability matrix
containing the transition
probabilities between states .
is the transition probability from state i to state j.
h
: Value of the control limit.
The value of ARL_0
will be printed to the console.
Daniel Gomon
Brook, D., & Evans, D. A. (1972). An Approach to the Probability Distribution of CUSUM Run Length. Biometrika, 59(3), 539-549. doi:10.2307/2334805
Steiner, S. H., Cook, R. J., Farewell, V. T., & Treasure, T. (2000). Monitoring surgical performance using risk-adjusted cumulative sum charts. Biostatistics, 1(4), 441-452. doi:10.1093/biostatistics/1.4.441
Kemp, K. W. (1971). Formal Expressions which Can Be Applied to Cusum Charts. Journal of the Royal Statistical Society. Series B (Methodological), 33(3), 331-360. doi:10.1111/j.2517-6161.1971.tb01521.x
bernoulli_cusum
, bernoulli_control_limit
#Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: glmmodber <- glm((survtime <= 100) & (censorid == 1)~ age + sex + BMI, data = surgerydat, family = binomial(link = "logit")) #Determine the Average Run Length in number of outcomes for #control limit h = 2.5 with (0, h) divided into n_grid = 200 segments ARL <- bernoulli_ARL(h = 2.5, n_grid = 200, glmmod = glmmodber, theta = log(2)) #Calculate ARL, but now exploiting connection between SPRT and CUSUM: #n_grid now decides the accuracy of the Trapezoidal rule for integral approximation ARLSPRT <- bernoulli_ARL(h = 2.5, n_grid = 200, glmmod = glmmodber, theta = log(2), method = "SPRT")
#Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: glmmodber <- glm((survtime <= 100) & (censorid == 1)~ age + sex + BMI, data = surgerydat, family = binomial(link = "logit")) #Determine the Average Run Length in number of outcomes for #control limit h = 2.5 with (0, h) divided into n_grid = 200 segments ARL <- bernoulli_ARL(h = 2.5, n_grid = 200, glmmod = glmmodber, theta = log(2)) #Calculate ARL, but now exploiting connection between SPRT and CUSUM: #n_grid now decides the accuracy of the Trapezoidal rule for integral approximation ARLSPRT <- bernoulli_ARL(h = 2.5, n_grid = 200, glmmod = glmmodber, theta = log(2), method = "SPRT")
This function can be used to determine control limits for the
Bernoulli CUSUM (bernoulli_cusum
) procedure by
restricting the type I error alpha
of the
procedure over time
.
bernoulli_control_limit(time, alpha = 0.05, followup, psi, n_sim = 200, glmmod, baseline_data, theta, p0, p1, h_precision = 0.01, seed = 1041996, pb = FALSE, assist)
bernoulli_control_limit(time, alpha = 0.05, followup, psi, n_sim = 200, glmmod, baseline_data, theta, p0, p1, h_precision = 0.01, seed = 1041996, pb = FALSE, assist)
time |
A numeric value over which the type I error |
alpha |
A proportion between 0 and 1 indicating the required maximal type I error. |
followup |
The value of the follow-up time to be used to determine event time.
Event time will be equal to |
psi |
A numeric value indicating the estimated Poisson arrival rate of subjects
at their respective units. Can be determined using
|
n_sim |
An integer value indicating the amount of units to generate for the determination of the control limit. Larger values yield more precise control limits, but increase computation times. Default is 200. |
glmmod |
Generalized linear regression model used for risk-adjustment as produced by
the function
|
baseline_data |
(optional): A
and optionally additional covariates used for risk-adjustment. Can only be specified
in combination with |
theta |
The
|
p0 |
The baseline failure probability at |
p1 |
The alternative hypothesis failure probability at |
h_precision |
(optional): A numerical value indicating how precisely the control limit should be determined. By default, control limits will be determined up to 2 significant digits. |
seed |
(optional): A numeric seed for survival time generation. Default is 01041996 (my birthday). |
pb |
(optional): A boolean indicating whether a progress bar should
be shown. Default is |
assist |
(optional): Output of the function |
This function performs 3 steps to determine a suitable control limit.
Step 1: Generates n_sim
in-control units (failure rate as baseline).
If data
is provided, subject covariates are resampled from the data set.
Step 2: Determines chart values for all simulated units.
Step 3: Determines control limits such that at most a proportion alpha
of all units cross the control limit.
The generated data as well as the charts are also returned in the output.
A list containing three components:
call
: the call used to obtain output;
charts
: A list of length n_sim
containing the constructed charts;
data
: A data.frame
containing the in-control generated data.
h
: Determined value of the control limit.
Daniel Gomon
Other control limit simulation:
bk_control_limit()
,
cgr_control_limit()
#We consider patient outcomes 100 days after their entry into the study. followup <- 100 #Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Determine control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted glm constructed on the baseline data. a <- bernoulli_control_limit(time = 500, alpha = 0.1, followup = followup, psi = 0.5, n_sim = 10, theta = log(2), glmmod = glmmodber, baseline_data = surgerydat) print(a$h)
#We consider patient outcomes 100 days after their entry into the study. followup <- 100 #Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Determine control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted glm constructed on the baseline data. a <- bernoulli_control_limit(time = 500, alpha = 0.1, followup = followup, psi = 0.5, n_sim = 10, theta = log(2), glmmod = glmmodber, baseline_data = surgerydat) print(a$h)
This function can be used to construct a risk-adjusted Bernoulli CUSUM chart for survival data. It requires the specification of one of the following combinations of parameters as arguments to the function:
glmmod
& theta
p0
& theta
p0
& p1
bernoulli_cusum(data, followup, glmmod, theta, p0, p1, h, stoptime, assist, twosided = FALSE)
bernoulli_cusum(data, followup, glmmod, theta, p0, p1, h, stoptime, assist, twosided = FALSE)
data |
A
and optionally additional covariates used for risk-adjustment. |
followup |
The value of the follow-up time to be used to determine event time.
Event time will be equal to |
glmmod |
Generalized linear regression model used for risk-adjustment as produced by
the function
|
theta |
The
|
p0 |
The baseline failure probability at |
p1 |
The alternative hypothesis failure probability at |
h |
(optional): Control limit to be used for the procedure. |
stoptime |
(optional): Time after which the value of the chart should no longer be determined. |
assist |
(optional): Output of the function |
twosided |
(optional): Should a two-sided Bernoulli CUSUM be constructed?
Default is |
The Bernoulli CUSUM chart is given by
where
and is the outcome of the
-th (chronological) subject in the data. In terms of the Odds Ratio:
For a risk-adjusted procedure (when glmmod
is specified), a patient specific baseline failure probability is modelled using logistic regression first.
Instead of the standard practice of displaying patient numbering on the
x-axis, the time of outcome is displayed.
An object of class bercusum
containing:
CUSUM
: A data.frame
containing the following named columns:
time
:times at which chart is constructed;
value
:value of the chart at corresponding times;
numobs
:number of observations at corresponding times.
call
: the call used to obtain output;
glmmod
: coefficients of the glm()
used
for risk-adjustment, if specified;
stopind
: indicator for whether the chart was stopped by the
control limit.
Daniel Gomon
plot.bercusum
, runlength.bercusum
#We consider patient outcomes 100 days after their entry into the study. followup <- 100 #Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Construct the Bernoulli CUSUM on the 1st hospital in the data set. bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 1), glmmod = glmmodber, followup = followup, theta = log(2)) #Plot the Bernoulli CUSUM plot(bercus)
#We consider patient outcomes 100 days after their entry into the study. followup <- 100 #Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Construct the Bernoulli CUSUM on the 1st hospital in the data set. bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 1), glmmod = glmmodber, followup = followup, theta = log(2)) #Plot the Bernoulli CUSUM plot(bercus)
Calculate the cdf of the Run Length of the Bernoulli CUSUM,
starting from initial value between 0 and h
, using Markov Chain methodology.
bernoulli_RL_cdf(h, x, n_grid, glmmod, theta, theta_true, p0, p1, smooth_prob = FALSE, exact = TRUE)
bernoulli_RL_cdf(h, x, n_grid, glmmod, theta, theta_true, p0, p1, smooth_prob = FALSE, exact = TRUE)
h |
Control limit for the Bernoulli CUSUM |
x |
Quantile at which to evaluate the cdf. |
n_grid |
Number of state spaces used to discretize the outcome space (when |
glmmod |
Generalized linear regression model used for risk-adjustment as produced by
the function
|
theta |
The
|
theta_true |
The true log odds ratio |
p0 |
The baseline failure probability at |
p1 |
The alternative hypothesis failure probability at |
smooth_prob |
Should the probability distribution of failure under the null distribution be smoothed?
Useful for small samples. Can only be TRUE when |
exact |
Should the cdf be determined exactly (TRUE), or approximately
(FALSE)? The approximation works well for large |
Let denote the run length of the Bernoulli CUSUM with control limit
h
, then
this function can be used to evaluate .
The formula on page 543 of Brook & Evans (1972)
is used if exact = TRUE
. When exact = FALSE
, formula (3.9) on
page 545 is used instead, approximating the transition matrix using its
Jordan canonical form. This can save computation time considerably, but is
not appropriate for small values of x
.
A list containing:
Fr_0
: A numeric value indicating the probability of the run
length being smaller than x
.
Fr
: A data.frame
containing the cumulative distribution function of the run length
depending on the state in which the process starts
start_val
:Starting value of the CUSUM, corresponding to the
discretized state spaces ;
P(K <= x)
:Value of the cdf at x
for the CUSUM with
initial value start_val
;
R
: A transition probability matrix
containing the transition
probabilities between states .
is the transition probability from state i to state j.
The value of ARL_0
will be printed to the console.
Brook, D., & Evans, D. A. (1972). An Approach to the Probability Distribution of CUSUM Run Length. Biometrika, 59(3), 539-549. doi:10.2307/2334805
Steiner, S. H., Cook, R. J., Farewell, V. T., & Treasure, T. (2000). Monitoring surgical performance using risk-adjusted cumulative sum charts. Biostatistics, 1(4), 441-452. doi:10.1093/biostatistics/1.4.441
#Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: glmmodber <- glm((survtime <= 100) & (censorid == 1)~ age + sex + BMI, data = surgerydat, family = binomial(link = "logit")) #Determine probability of run length being less than 600 prob600 <- bernoulli_RL_cdf(h = 2.5, x = 600, n_grid = 200, glmmod = glmmodber, theta = log(2))
#Determine a risk-adjustment model using a generalized linear model. #Outcome (failure within 100 days) is regressed on the available covariates: glmmodber <- glm((survtime <= 100) & (censorid == 1)~ age + sex + BMI, data = surgerydat, family = binomial(link = "logit")) #Determine probability of run length being less than 600 prob600 <- bernoulli_RL_cdf(h = 2.5, x = 600, n_grid = 200, glmmod = glmmodber, theta = log(2))
This function can be used to determine control limits for the
BK-CUSUM (bk_cusum
) procedure by restricting the type I error alpha
of the
procedure over time
.
bk_control_limit(time, alpha = 0.05, psi, n_sim = 200, theta, coxphmod, baseline_data, cbaseh, inv_cbaseh, interval = c(0, 9e+12), h_precision = 0.01, seed = 1041996, pb = FALSE, chartpb = FALSE, assist)
bk_control_limit(time, alpha = 0.05, psi, n_sim = 200, theta, coxphmod, baseline_data, cbaseh, inv_cbaseh, interval = c(0, 9e+12), h_precision = 0.01, seed = 1041996, pb = FALSE, chartpb = FALSE, assist)
time |
A numeric value over which the type I error |
alpha |
A proportion between 0 and 1 indicating the required maximal type I error. Default is 0.05. |
psi |
A numeric value indicating the estimated Poisson arrival rate of subjects
at their respective units. Can be determined using
|
n_sim |
An integer value indicating the amount of units to generate for the determination of the control limit. Larger values yield more precise control limits, but increase computation times. Default is 200. |
theta |
The expected log-hazard ratio |
coxphmod |
A Cox proportional hazards regression model as
produced by
the function
|
baseline_data |
(optional): A
and optionally additional covariates used for risk-adjustment. Can only be specified
in combination with |
cbaseh |
A function that returns the unadjusted cumulative
baseline hazard |
inv_cbaseh |
(optional): A function that returns the unadjusted inverse cumulative
baseline
hazard |
interval |
(optional): Interval in which survival times should be solved for numerically. |
h_precision |
(optional): A numerical value indicating how precisely the control limit should be determined. By default, control limits will be determined up to 2 significant digits. |
seed |
(optional): A numeric seed for survival time generation. Default is 01041996 (my birthday). |
pb |
(optional): A boolean indicating whether a progress bar should
be shown. Default is |
chartpb |
(optional): A boolean indicating whether progress bars should
be displayed for the constructions of the charts. Default is |
assist |
(optional): Output of the function |
This function performs 3 steps to determine a suitable control limit.
Step 1: Generates n_sim
in-control units (failure rate as baseline).
If data
is provided, subject covariates are resampled from the data set.
Step 2: Determines chart values for all simulated units.
Step 3: Determines control limits such that at most a proportion alpha
of all units cross the control limit.
The generated data as well as the charts are also returned in the output.
A list containing three components:
call
: the call used to obtain output;
charts
: A list of length n_sim
containing the constructed charts;
data
: A data.frame
containing the in-control generated data.
h
: Determined value of the control limit.
achieved_alpha
: Achieved type I error on the sample of
n_sim
simulated units.
Daniel Gomon
Other control limit simulation:
bernoulli_control_limit()
,
cgr_control_limit()
require(survival) #Determine a cox proportional hazards model for risk-adjustment exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine a control limit restricting type I error to 0.1 over 500 days #with specified cumulative hazard function without risk-adjustment a <- bk_control_limit(time = 500, alpha = 0.1, theta = log(2), cbaseh = function(t) chaz_exp(t, lambda = 0.02), inv_cbaseh = function(t) inv_chaz_exp(t, lambda = 0.02), psi = 0.5, n_sim = 10) #Determine a control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted cumulative hazard determined using coxph() b <- bk_control_limit(time = 500, alpha = 0.1, theta = log(2), coxphmod = tcoxmod, psi = 0.5, n_sim = 10) print(a$h) print(b$h)
require(survival) #Determine a cox proportional hazards model for risk-adjustment exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine a control limit restricting type I error to 0.1 over 500 days #with specified cumulative hazard function without risk-adjustment a <- bk_control_limit(time = 500, alpha = 0.1, theta = log(2), cbaseh = function(t) chaz_exp(t, lambda = 0.02), inv_cbaseh = function(t) inv_chaz_exp(t, lambda = 0.02), psi = 0.5, n_sim = 10) #Determine a control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted cumulative hazard determined using coxph() b <- bk_control_limit(time = 500, alpha = 0.1, theta = log(2), coxphmod = tcoxmod, psi = 0.5, n_sim = 10) print(a$h) print(b$h)
This function implements the BK-CUSUM procedure based on the
Biswas & Kalbfleisch (2008) CUSUM. To construct the Biswas & Kalbfleisch
(2008) CUSUM, set C = 1
(years) or C = 365
(days).
For detection purposes, it is sufficient
to determine the value of the chart at the times of failure. This can be
achieved by leaving ctimes
unspecified.
The function requires the specification of theta
and
has two vital parameters, at least one of which must be specified:
coxphmod
: Cox proportional hazards model to be used for
risk-adjustment. If cbaseh
is not specified, it will be determined
from coxphmod
numerically.
cbaseh
: The cumulative baseline hazard rate to use for chart
construction. If specified with coxphmod
missing, no risk-adjustment
will be performed
bk_cusum(data, theta, coxphmod, cbaseh, ctimes, h, stoptime, C, twosided = FALSE, pb = FALSE, assist)
bk_cusum(data, theta, coxphmod, cbaseh, ctimes, h, stoptime, C, twosided = FALSE, pb = FALSE, assist)
data |
A
and optionally additional covariates used for risk-adjustment. |
theta |
The expected log-hazard ratio |
coxphmod |
A Cox proportional hazards regression model as
produced by
the function
|
cbaseh |
A function that returns the unadjusted cumulative
baseline hazard |
ctimes |
(optional): Vector of construction times at which the value of the chart should be determined. When not specified, the chart is constructed at all failure times. |
h |
(optional): Value of the control limit. The chart will only be constructed until the value of the control limit has been reached or surpassed. |
stoptime |
(optional): Time after which the value of the chart should no longer be determined. Default = max(failure time). Useful when ctimes has not been specified. |
C |
(optional): A numeric value indicating how long after entering the study
patients should no longer influence the value of the chart. This is
equivalent to right-censoring every observation at time |
twosided |
(optional): A boolean indicating whether a two-sided CUSUM
should be constructed.
If |
pb |
(optional): A boolean indicating whether a progress bar should
be shown. Default is |
assist |
(optional): Output of the function |
The BK-CUSUM can be used to test the alternative hypothesis of an
instant change of fixed size
in the subject specific hazard rate from
to
. The parameter
C
can be used
to ignore the contributions of subjects, C time units after their entry
into the study.
The BK-CUSUM is constructed as
where is the log expected hazard ratio,
with the counting process of all failures at time t, and
with the summed cumulative intensity of all
subjects at time
.
An object of class bkcusum
containing:
BK
: a data.frame
containing the following named columns:
time
:times at which chart is constructed;
value
:value of the chart at corresponding times.
stopind
: indicator for whether the chart was stopped by
the control limit;
call
: the call used to obtain output;
h
: Specified value for the control limit.
Daniel Gomon
Biswas P. and Kalbfleisch J.D. (2008), A risk-adjusted CUSUM in continuous time based on the Cox Model, Statistics in medicine 27, 3452-3452. doi:10.1002/sim.3216
plot.bkcusum
, runlength.bkcusum
Other quality control charts:
cgr_cusum()
,
funnel_plot()
require(survival) #Select only the data of the first hospital in the surgerydat data set tdat <- subset(surgerydat, unit == 1) #We know that the cumulative baseline hazard in the data set is #Exponential(0.01). If you don't know the cumulative baseline, we suggest #leaving the cbaseh argument empty and determining a coxphmod (see help) tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) #Determine a risk-adjustment model using a Cox proportional hazards model. #Outcome (survival) is regressed on the available covariates: exprfit <- Surv(survtime, censorid) ~ age + sex + BMI tcoxmod <- coxph(exprfit, data= surgerydat) #Determine the values of the chart bk <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) #plot the BK-CUSUM (exact hazard) plot(bk) #Alternatively, cbaseh can be left empty when specifying coxphmod through coxph() bk_cox <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, pb = TRUE) #plot the BK-CUSUM (estimated hazard from coxph) plot(bk_cox)
require(survival) #Select only the data of the first hospital in the surgerydat data set tdat <- subset(surgerydat, unit == 1) #We know that the cumulative baseline hazard in the data set is #Exponential(0.01). If you don't know the cumulative baseline, we suggest #leaving the cbaseh argument empty and determining a coxphmod (see help) tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) #Determine a risk-adjustment model using a Cox proportional hazards model. #Outcome (survival) is regressed on the available covariates: exprfit <- Surv(survtime, censorid) ~ age + sex + BMI tcoxmod <- coxph(exprfit, data= surgerydat) #Determine the values of the chart bk <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) #plot the BK-CUSUM (exact hazard) plot(bk) #Alternatively, cbaseh can be left empty when specifying coxphmod through coxph() bk_cox <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, pb = TRUE) #plot the BK-CUSUM (estimated hazard from coxph) plot(bk_cox)
Data about patient survival after their breast cancer surgery procedure performed at one of the 15 units participating in a cancer treatment study. The data is based on a trial performed at the European Organisation for Research and Treatment of Cancer (EORTC).
breast
breast
A data.frame
with 2663 rows and 11 variables:
Chronological time of entry of patient into study/time of surgery (numeric)
Time from entry until failure of patient (numeric)
Censoring indicator (0 - right censored, 1 - observed) (integer)
Unit number at which patient received treatment (integer)
Covariates associated with patient (factor)
Based on trial data from the European Organisation for Research and Treatment of Cancer, https://www.eortc.org/
#Determine the estimated arrival rate for all units in the data arrival_rate(breast) #Plot Quality Control charts for unit 11 in the study library(survival) phmodbreast <- coxph(Surv(survtime, censorid) ~ . - entrytime - unit , data = breast) glmmodbreast <- glm((survtime <= 36) & (censorid == 1) ~ . - entrytime - unit, data = breast, family = binomial(link = "logit")) par(mfrow = c(1, 3)) p1 <- plot(cgr_cusum(data = subset(breast, unit == 11), coxphmod = phmodbreast)) + ggtitle("CGR-CUSUM") p2 <- plot(bk_cusum(data = subset(breast, unit == 11), coxphmod = phmodbreast, theta = log(2))) + ggtitle("BK-CUSUM") p3 <- plot(bernoulli_cusum(data = subset(breast, unit == 11), followup = 36, glmmod = glmmodbreast, theta = log(2))) + ggtitle("Bernoulli CUSUM") p4 <- plot(funnel_plot(data = breast, glmmod = glmmodbreast, followup = 36 )) + ggtitle("Funnel plot") if(require("gridExtra")){ grid.arrange(p1, p2, p3, p4, nrow = 2) }
#Determine the estimated arrival rate for all units in the data arrival_rate(breast) #Plot Quality Control charts for unit 11 in the study library(survival) phmodbreast <- coxph(Surv(survtime, censorid) ~ . - entrytime - unit , data = breast) glmmodbreast <- glm((survtime <= 36) & (censorid == 1) ~ . - entrytime - unit, data = breast, family = binomial(link = "logit")) par(mfrow = c(1, 3)) p1 <- plot(cgr_cusum(data = subset(breast, unit == 11), coxphmod = phmodbreast)) + ggtitle("CGR-CUSUM") p2 <- plot(bk_cusum(data = subset(breast, unit == 11), coxphmod = phmodbreast, theta = log(2))) + ggtitle("BK-CUSUM") p3 <- plot(bernoulli_cusum(data = subset(breast, unit == 11), followup = 36, glmmod = glmmodbreast, theta = log(2))) + ggtitle("Bernoulli CUSUM") p4 <- plot(funnel_plot(data = breast, glmmod = glmmodbreast, followup = 36 )) + ggtitle("Funnel plot") if(require("gridExtra")){ grid.arrange(p1, p2, p3, p4, nrow = 2) }
This function can be used to calculate the change in the relative risk of a subject pertaining to their covariates under a specified Cox proportional hazards model.
calc_risk(data, coxphmod = NULL)
calc_risk(data, coxphmod = NULL)
data |
A data frame containing the covariates to be used for risk-adjustment as named columns. |
coxphmod |
(optional): A cox proportional hazards model generated using
|
The subject-specific relative risk is
,
where
is a vector of regression coefficients
and
a vector of covariates for subject i.
A vector of nrow(data)
specifying the increased/decreased
risk of failure for each subject.
Daniel Gomon
#Small example data crdat <- data.frame(age = rnorm(10, 40, 5), BMI = rnorm(10, 24, 3)) #Example risk-adjustment list (can also specify coxphmod) crlist <- list(formula = as.formula("~age + BMI"), coefficients = c("age"= 0.02, "BMI"= 0.009)) #Calculate the increase or decrease of the relative risk for the subjects #in crdat. calc_risk(crdat, crlist)
#Small example data crdat <- data.frame(age = rnorm(10, 40, 5), BMI = rnorm(10, 24, 3)) #Example risk-adjustment list (can also specify coxphmod) crlist <- list(formula = as.formula("~age + BMI"), coefficients = c("age"= 0.02, "BMI"= 0.009)) #Calculate the increase or decrease of the relative risk for the subjects #in crdat. calc_risk(crdat, crlist)
This function can be used to determine control limits for the
CGR-CUSUM (cgr_cusum
) procedure by restricting the type I error alpha
of the
procedure over time
.
cgr_control_limit(time, alpha = 0.05, psi, n_sim = 20, coxphmod, baseline_data, cbaseh, inv_cbaseh, interval = c(0, 9e+12), h_precision = 0.01, ncores = 1, seed = 1041996, pb = FALSE, chartpb = FALSE, detection = "upper", maxtheta = log(6), assist)
cgr_control_limit(time, alpha = 0.05, psi, n_sim = 20, coxphmod, baseline_data, cbaseh, inv_cbaseh, interval = c(0, 9e+12), h_precision = 0.01, ncores = 1, seed = 1041996, pb = FALSE, chartpb = FALSE, detection = "upper", maxtheta = log(6), assist)
time |
A numeric value over which the type I error |
alpha |
A proportion between 0 and 1 indicating the required maximal type I error. Default is 0.05. |
psi |
A numeric value indicating the estimated Poisson arrival rate of subjects
at their respective units. Can be determined using
|
n_sim |
An integer value indicating the amount of units to generate for the determination of the control limit. Larger values yield more precise control limits, but greatly increase computation times. Default is 20. |
coxphmod |
(optional): A cox proportional hazards regression model as
produced by
the function
|
baseline_data |
(optional): A
and optionally additional covariates used for risk-adjustment. Can only be specified
in combination with |
cbaseh |
(optional): A function that returns the unadjusted cumulative
baseline hazard |
inv_cbaseh |
(optional): A function that returns the unadjusted inverse cumulative
baseline
hazard |
interval |
(optional): Interval in which survival times should be solved for numerically. |
h_precision |
(optional): A numerical value indicating how precisely the control limit should be determined. By default, control limits will be determined up to 2 significant digits. |
ncores |
(optional): Number of cores to use to parallelize the computation of the
CGR-CUSUM charts. If ncores = 1 (default), no parallelization is done. You
can use |
seed |
(optional): A numeric seed for survival time generation. Default = my birthday. |
pb |
(optional): A boolean indicating whether a progress bar should
be shown. Default is |
chartpb |
(optional): A boolean indicating whether progress bars should
be displayed for the constructions of the charts. Default is |
detection |
Should the control limit be determined for an
|
maxtheta |
(optional): Maximum value of maximum likelihood estimate for
parameter |
assist |
(optional): Output of the function |
This function performs 3 steps to determine a suitable control limit.
Step 1: Generates n_sim
in-control units (failure rate as baseline).
If data
is provided, subject covariates are resampled from the data set.
Step 2: Determines chart values for all simulated units.
Step 3: Determines control limits such that at most a proportion alpha
of all units cross the control limit.
The generated data as well as the charts are also returned in the output.
A list containing three components:
call
: the call used to obtain output;
charts
: A list of length n_sim
containing the constructed charts;
data
: A data.frame
containing the in-control generated data.
h
: Determined value of the control limit.
achieved_alpha
: Achieved type I error on the sample of
n_sim
simulated units.
Daniel Gomon
Other control limit simulation:
bernoulli_control_limit()
,
bk_control_limit()
require(survival) #Determine a cox proportional hazards model for risk-adjustment exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine a control limit restricting type I error to 0.1 over 500 days #with specified cumulative hazard function without risk-adjustment a <- cgr_control_limit(time = 500, alpha = 0.1, cbaseh = function(t) chaz_exp(t, lambda = 0.02), inv_cbaseh = function(t) inv_chaz_exp(t, lambda = 0.02), psi = 0.5, n_sim = 10) #Determine a control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted cumulative hazard found using coxph() b <- cgr_control_limit(time = 500, alpha = 0.1, coxphmod = tcoxmod, psi = 0.5, n_sim = 10, baseline_data = subset(surgerydat, unit == 1)) print(a$h) print(b$h)
require(survival) #Determine a cox proportional hazards model for risk-adjustment exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine a control limit restricting type I error to 0.1 over 500 days #with specified cumulative hazard function without risk-adjustment a <- cgr_control_limit(time = 500, alpha = 0.1, cbaseh = function(t) chaz_exp(t, lambda = 0.02), inv_cbaseh = function(t) inv_chaz_exp(t, lambda = 0.02), psi = 0.5, n_sim = 10) #Determine a control limit restricting type I error to 0.1 over 500 days #using the risk-adjusted cumulative hazard found using coxph() b <- cgr_control_limit(time = 500, alpha = 0.1, coxphmod = tcoxmod, psi = 0.5, n_sim = 10, baseline_data = subset(surgerydat, unit == 1)) print(a$h) print(b$h)
This function performs the CGR-CUSUM procedure
described in Gomon et al. (2022). For detection purposes, it suffices
to determine the value of the chart at the times of failure. This can be
achieved by leaving ctimes
unspecified.
The function has two vital parameters, at least one of which must be specified:
coxphmod
: Cox proportional hazards model to be used for
risk-adjustment. If cbaseh
is not specified, it will be determined
from coxphmod
numerically.
cbaseh
: The cumulative baseline hazard rate to use for chart
construction. If specified with coxphmod
missing, no risk-adjustment
will be performed
cgr_cusum(data, coxphmod, cbaseh, ctimes, h, stoptime, C, pb = FALSE, ncores = 1, cmethod = "memory", dependencies, detection = "upper", assist, maxtheta = log(6))
cgr_cusum(data, coxphmod, cbaseh, ctimes, h, stoptime, C, pb = FALSE, ncores = 1, cmethod = "memory", dependencies, detection = "upper", assist, maxtheta = log(6))
data |
A
and optionally additional covariates used for risk-adjustment. |
coxphmod |
A Cox proportional hazards regression model as
produced by
the function
|
cbaseh |
A function that returns the unadjusted cumulative
baseline hazard |
ctimes |
(optional): Vector of construction times at which the value of the chart should be determined. When not specified, the chart is constructed at all failure times. |
h |
(optional): Value of the control limit. The chart will only be constructed until the value of the control limit has been reached or surpassed. |
stoptime |
(optional): Time after which the value of the chart should no longer be determined. Default = max(failure time). Useful when ctimes has not been specified. |
C |
(optional): A numeric value indicating how long after entering the study
patients should no longer influence the value of the chart. This is
equivalent to right-censoring every observation at time |
pb |
(optional): A boolean indicating whether a progress bar should
be shown. Default is |
ncores |
number of cores to use to parallelize the computation of the
CGR-CUSUM chart. If ncores = 1 (default), no parallelization is done. You
can use |
cmethod |
Method to calculate chart values. One of the following:
|
dependencies |
(optional): When |
detection |
Should an |
assist |
(optional): Output of the function |
maxtheta |
(optional): Maximum value the maximum likelihood estimate for
parameter |
The CGR-CUSUM can be used to test for a change of unknown positive fixed size
in the subject-specific hazard rate from
to
starting from some unknown subject
. The starting time of the first subject
who had an increase in failure rate as well as the estimated increase in the
hazard rate are shown in the output.
The CGR-CUSUM is determined as
where
with the counting process for the failure at time
of subject
and
where is the cumulative intensity of subject
at time
.
When maxtheta
is specified, the maximum likelihood estimate of
is restricted to either
abs(maxtheta)
(upper sided CGR-CUSUM) or
-abs(maxtheta)
(lower sided CGR-CUSUM). Choosing this value smaller leads to smaller
control limits and therefore quicker detection times, but can cause delays in
detection if the true increase in failure rate is larger than the cut-off. The
default of expecting at most a 6 times increase in hazard/odds ratio can therefore
be the wrong choice for your intended application area. If unsure, the most conservative
choice is to take maxtheta = Inf
.
An object of class "cgrcusum" containing:
CGR
: a data.frame
with named columns:
time
:times at which chart is constructed;
value
:value of the chart at corresponding times;
exp_theta_t
:value of MLE ;
S_nu
time from which patients are considered for constructing the chart.
call
: the call used to obtain output;
stopind
: indicator for whether the chart was stopped by
the control limit;
h
: Specified value for the control limit.
Daniel Gomon
Gomon, D. and Putter, H. and Nelissen, R. G. H. H. and van der Pas, S. (2022), CGR-CUSUM: A Continuous time Generalized Rapid Response Cumulative Sum chart, Biostatistics doi:10.1093/biostatistics/kxac041
Gomon D. and Fiocco M and Putter H and Signorelli M, SUrvival Control Chart EStimation Software in R: the success Package, The R Journal, vol. 15, no. 4, pp. 270–291, Dec. 2023, doi:10.32614/rj-2023-095
plot.cgrcusum
, runlength.cgrcusum
Other quality control charts:
bk_cusum()
,
funnel_plot()
require(survival) #Select only the data of the first year of the first hospital in the surgerydat data set tdat <- subset(surgerydat, unit == 1 & entrytime < 365) #We know that the cumulative baseline hazard in the data set is #Exponential(0.01). If you don't know the cumulative baseline, we suggest #leaving the cbaseh argument empty and determining a coxphmod (see help) tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) #Determine a risk-adjustment model using a Cox proportional hazards model. #Outcome (survival) is regressed on the available covariates: exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine the values of the chart cgr <- cgr_cusum(data = tdat, coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) #plot the CGR-CUSUM (exact hazard) plot(cgr) #Alternatively, cbaseh can be left empty when specifying coxphmod through coxph() cgr_cox <- cgr_cusum(data = tdat, coxphmod = tcoxmod, pb = TRUE) #plot the CGR-CUSUM (estimated hazard from coxph) plot(cgr_cox)
require(survival) #Select only the data of the first year of the first hospital in the surgerydat data set tdat <- subset(surgerydat, unit == 1 & entrytime < 365) #We know that the cumulative baseline hazard in the data set is #Exponential(0.01). If you don't know the cumulative baseline, we suggest #leaving the cbaseh argument empty and determining a coxphmod (see help) tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) #Determine a risk-adjustment model using a Cox proportional hazards model. #Outcome (survival) is regressed on the available covariates: exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Determine the values of the chart cgr <- cgr_cusum(data = tdat, coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) #plot the CGR-CUSUM (exact hazard) plot(cgr) #Alternatively, cbaseh can be left empty when specifying coxphmod through coxph() cgr_cox <- cgr_cusum(data = tdat, coxphmod = tcoxmod, pb = TRUE) #plot the CGR-CUSUM (estimated hazard from coxph) plot(cgr_cox)
Functions which return the hazard, cumulative
hazard and inverse cumulative hazard at time t for an exponential distribution
with parameter and true hazard ratio
.
haz_exp(t, lambda, mu = log(1)) chaz_exp(t, lambda, mu = log(1)) inv_chaz_exp(t, lambda, mu = log(1))
haz_exp(t, lambda, mu = log(1)) chaz_exp(t, lambda, mu = log(1)) inv_chaz_exp(t, lambda, mu = log(1))
t |
time of evaluation. |
lambda |
parameter of the exponential distribution. |
mu |
(optional) true excess hazard rate |
The hazard function of an exponential distribution is given by:
The cumulative hazard (with true hazard ratio ) is given by:
The inverse cumulative hazard (with true hazard ratio ) by:
Value of specified function at time .
Extracts a function which returns the (inverse) cumulative
baseline hazard from a coxph()
call.
extract_hazard(coxphmod)
extract_hazard(coxphmod)
coxphmod |
A call to |
The baseline hazard is extracted from the coxph()
call using the basehaz()
function. The
baseline hazard function is then smoothed using
approxfun()
to obtain the linear interpolant.
If required, the inverse baseline hazard is determined using root linear
interpolation. For this, a function written by Zheyuan Li (see references) is used.
A list containing:
cbaseh
: A function which returns the cumulative baseline hazard
at specified time;
inv_cbaseh
: A function which returns the inverse cumulative
baseline hazard at specified time.
max_time
: maximal time at which cbaseh
is known;
max_haz
: value of maximal hazard (at maximum time).
Daniel Gomon
Zheyuan Li: How to estimate x value from y value input after approxfun in R? (accessed: 09/10/2023)
require(survival) exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) tcox_hazard_fcts <- extract_hazard(tcoxmod)
require(survival) exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) tcox_hazard_fcts <- extract_hazard(tcoxmod)
This function allows to construct a risk-adjusted funnel plot for comparing survival proportion between units, see Spiegelhalter (2005).
funnel_plot(data, ctime, p0, glmmod, followup, predlim = c(0.95, 0.99), assist)
funnel_plot(data, ctime, p0, glmmod, followup, predlim = c(0.95, 0.99), assist)
data |
A
and optionally additional covariates used for risk-adjustment. |
ctime |
Construction time at which the funnel plot should be determined. Maximum possible time used when not specified. |
p0 |
The baseline failure probability at |
glmmod |
A generalized linear regression model as produced by
the function
|
followup |
The followup time for every individual. At what time after subject entry do we consider the outcome? |
predlim |
A vector of confidence levels for the prediction limits of interest. Default is c(0.95, 0.99). |
assist |
(optional): Output of the function |
An object of class "funnelplot" containing:
data
: A data.frame
containing:
unit
:unit number/name;
observed
:observed number of failures at unit;
expected
:expected (risk-adjusted) number of failures at unit;
numtotal
total number of individuals considered at this unit;
p
:(risk-adjusted) proportion of failure at unit;
predlimels
:worse/in-control/better performance than expected at specified confidence levels.
call
: the call used to obtain output
plotdata
: data used for plotting confidence intervals
predlim
: specified confidence level(s)
p0
: (Estimated) baseline failure probability
Daniel Gomon
Spiegelhalter D. J. (2005). Funnel plots for comparing institutional performance. Statistics in medicine, 24(8), 1185-1202. doi:10.1002/sim.1970
plot.funnelplot
, summary.funnelplot
Other quality control charts:
bk_cusum()
,
cgr_cusum()
#Determine a risk-adjustment model using a generalized linear model. #Outcome (survival in first 100 days) is regressed on the available covariates: exprfitfunnel <- as.formula("(survtime <= 100) & (censorid == 1)~ age + sex + BMI") glmmodfun <- glm(exprfitfunnel, data = surgerydat, family = binomial(link = "logit")) #Determine the necessary values to produce a funnel plot funnel <- funnel_plot(data = surgerydat, ctime = 3*365, glmmod = glmmodfun, followup = 100) #Produce a funnel plot! plot(funnel) ## Not run: require(plotly) #Create an interactive plot! ggplotly(plot(funnel)) ## End(Not run)
#Determine a risk-adjustment model using a generalized linear model. #Outcome (survival in first 100 days) is regressed on the available covariates: exprfitfunnel <- as.formula("(survtime <= 100) & (censorid == 1)~ age + sex + BMI") glmmodfun <- glm(exprfitfunnel, data = surgerydat, family = binomial(link = "logit")) #Determine the necessary values to produce a funnel plot funnel <- funnel_plot(data = surgerydat, ctime = 3*365, glmmod = glmmodfun, followup = 100) #Produce a funnel plot! plot(funnel) ## Not run: require(plotly) #Create an interactive plot! ggplotly(plot(funnel)) ## End(Not run)
This function can be used to generate arrival times for a Poisson point process with rate psi up until time t.
gen_arriv_times(psi, t)
gen_arriv_times(psi, t)
psi |
rate of the arrival process. |
t |
time until which arrivals should be generated. |
Exponential() interarrival times.
A vector of arrival times up until time t.
Daniel Gomon
set.seed(123) gen_arriv_times(psi = 0.3, t = 5) gen_arriv_times(psi = 0.3, t = 20)
set.seed(123) gen_arriv_times(psi = 0.3, t = 5) gen_arriv_times(psi = 0.3, t = 20)
Generate survival times according to hazard rate
with
the hazard rate associated with the
specified inverse cumulative hazard rate
invchaz
and the
specified true hazard ratio
mu
. See Bender et al. (2005).
gen_surv_times(invchaz, mu = log(1), data, coxphmod = NULL)
gen_surv_times(invchaz, mu = log(1), data, coxphmod = NULL)
invchaz |
the inverse cumulative (baseline) hazard rate to be used for generating survival times. Must take vector inputs! |
mu |
the true hazard ratio used to generate survival times. |
data |
an integer number of survival times to generate or
(in combination with coxphmod): a |
coxphmod |
(optional) a cox proportional hazards regression model as produced by
the function
|
Sometimes it is desirable to generate survival times from an increased hazard rate
with the baseline hazard rate. We call
the true hazard ratio.
A vector of survival times from subject entry time.
Daniel Gomon
Bender, R., Augustin, T., & Blettner, M. (2005). Generating survival times to simulate Cox proportional hazards models. Statistics in Medicine, 24(11), 1713-1723. doi:10.1002/sim.2059
set.seed(123) gen_surv_times(invchaz = function(t) inv_chaz_exp(t, lambda = 0.01), data = 5)
set.seed(123) gen_surv_times(invchaz = function(t) inv_chaz_exp(t, lambda = 0.01), data = 5)
Generate n_sim
units with subjects arriving according to
a Poisson
process with rate psi
until time
. Failure rate is determined
either from cbaseh
or inv_cbaseh
, or from specified
coxphmod
. Covariates will be resampled from baseline_data
if
specified.
generate_units(time, psi, n_sim = 20, cbaseh, inv_cbaseh, coxphmod = NULL, baseline_data, interval = c(0, 9e+12), mu = 0)
generate_units(time, psi, n_sim = 20, cbaseh, inv_cbaseh, coxphmod = NULL, baseline_data, interval = c(0, 9e+12), mu = 0)
time |
A numeric value indicating until what time from the start of the study subjects can arrive. |
psi |
Poisson arrival rate for subjects. |
n_sim |
An integer indicating how many units should be generated. Default is 20. |
cbaseh |
A function returning the cumulative baseline hazard
at each relevant time point. Will be numerically inverted to generate
failure times. If
the inverse cumulative baseline hazard function is available, please specify
|
inv_cbaseh |
A function returning the inverse cumulative baseline hazard at each relevant time point. |
coxphmod |
(optional): A cox proportional hazards model generated using
If both |
baseline_data |
(optional): A |
interval |
(optional) A numeric vector of length 2 indicating in which range of values the failure times of subjects should be determined. By default, failure times will be restricted between 0 and 9e12. |
mu |
(optional) The increased log hazard ratio at the generated units with respect to the specified baseline hazard rate. Default is log(1) = 0. |
In a Poisson arrival process, inter-arrival times are exponentially
distributed with parameter psi
. If cbaseh
is specified,
the inverse baseline hazard will be determined using uniroot()
.
The times of failure are then determined using gen_surv_times()
.
A data.frame
with rows representing subjects and the
following named columns:
entrytime
:time of subject entry into the study;
survtime
:survival time of subject;
censorid
:censoring indicator, 0 = censored, 1 = observed;
unit
:unit number;
expmu
:exponent of the log hazard ratio used to generate survival times;
psival
:arrival rate at unit;
covariates
:covariates resampled from baseline_data
.
Daniel Gomon
require(survival) #Fit a Cox model exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Generate 30 hospitals with on average 2 patients per day arriving #according to the Cox model determined above, with resampling from the #original data set. The hazard rate at the hospitals is twice the baseline #hazard. generate_units(time = 50, psi = 2, n_sim = 30, coxphmod = tcoxmod, baseline_data = surgerydat, mu = log(2))
require(survival) #Fit a Cox model exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) #Generate 30 hospitals with on average 2 patients per day arriving #according to the Cox model determined above, with resampling from the #original data set. The hazard rate at the hospitals is twice the baseline #hazard. generate_units(time = 50, psi = 2, n_sim = 30, coxphmod = tcoxmod, baseline_data = surgerydat, mu = log(2))
Create an interactive plot visualizing a combination of control charts which can be created using this package.
interactive_plot(x, unit_names, scale = FALSE, group_by = c("none", "unit", "type"), highlight = FALSE, manual_colors = c(), ...)
interactive_plot(x, unit_names, scale = FALSE, group_by = c("none", "unit", "type"), highlight = FALSE, manual_colors = c(), ...)
x |
A list with each item containing one cumulative sum chart. |
unit_names |
The unit names to be displayed in the interactive plot.
Must be of equal length as |
scale |
Should charts be scaled with respect to their control limit/
maximum value? Default is |
group_by |
Character indicating how to group the CUSUM charts in the plot.
Possible values are |
highlight |
Should charts be highlighted on hover? Default is |
manual_colors |
A character vector specifying which colors to use
for the units in the data. By default, the "Set2" color set from
|
... |
Further plotting parameters |
An interactive plot will be produced in the current graphics device. For more information on the possibilities for interaction, see https://plotly.com/r/.
cgr_cusum
, bk_cusum
, bernoulli_cusum
, funnel_plot
require(survival) #Extract data to construct CUSUM charts on tdat <- subset(surgerydat, unit == 1 & entrytime < 365) tdat2 <- subset(surgerydat, unit == 2 & entrytime < 365) #Determine model parameters followup <- 100 tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Construct the charts cgr <- cgr_cusum(data = tdat, coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) cgr$h <- 8.29 bk <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) bk$h <- 6.23 bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 1), glmmod = glmmodber, followup = followup, theta = log(2)) bercus$h <- 3.36 bk2 <- bk_cusum(data = tdat2, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) bk2$h <- 6.23 #Create the plot interactive_plot(list(cgr, bk, bercus, bk2), unit_names = c("hosp1", "hosp1", "hosp1", "hosp2"))
require(survival) #Extract data to construct CUSUM charts on tdat <- subset(surgerydat, unit == 1 & entrytime < 365) tdat2 <- subset(surgerydat, unit == 2 & entrytime < 365) #Determine model parameters followup <- 100 tcbaseh <- function(t) chaz_exp(t, lambda = 0.01) exprfit <- as.formula("Surv(survtime, censorid) ~ age + sex + BMI") tcoxmod <- coxph(exprfit, data= surgerydat) exprfitber <- as.formula("(survtime <= followup) & (censorid == 1)~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) #Construct the charts cgr <- cgr_cusum(data = tdat, coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) cgr$h <- 8.29 bk <- bk_cusum(data = tdat, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) bk$h <- 6.23 bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 1), glmmod = glmmodber, followup = followup, theta = log(2)) bercus$h <- 3.36 bk2 <- bk_cusum(data = tdat2, theta = log(2), coxphmod = tcoxmod, cbaseh = tcbaseh, pb = TRUE) bk2$h <- 6.23 #Create the plot interactive_plot(list(cgr, bk, bercus, bk2), unit_names = c("hosp1", "hosp1", "hosp1", "hosp2"))
This function can be used to determine some of the vital parameters used to construct control charts in this package.
parameter_assist(baseline_data, data, formula, followup, theta = log(2), time, alpha = 0.05, maxtheta = log(6))
parameter_assist(baseline_data, data, formula, followup, theta = log(2), time, alpha = 0.05, maxtheta = log(6))
baseline_data |
A
and optionally additional covariates used for risk-adjustment. |
data |
A
and optionally additional covariates used for risk-adjustment. |
formula |
A formula with right-hand side (RHS) indicating the form in which the covariates should be used for the Cox and GLM regression models. LHS of the formula will be ignored, and can be left empty. |
followup |
(optional): The value of the follow-up time to be used to determine event time.
Event time will be equal to |
theta |
The value of the expected log-hazard/odds ratio. In other words: the logarithm of the expected increase in the odds/hazard ratio. Default is log(2) (detecting a doubling of the odds/failure rate). |
time |
Timeframe over which the type I error of the control chart should be
limited. Should be in the same unit as |
alpha |
Required maximal type I error (between 0 and 1) of the procedure
over the timeframe specified in |
maxtheta |
Maximum value the maximum likelihood estimate for
parameter |
Depending on the specified arguments, the function will return
parameters. If covariate_names
is not specified, the returned
risk-adjustment models will be trivial. If formula
is not specified
but covariate_names
are,
the function assumes the simplest form for the regression model
(cov1 + cov2 + ...). If followup
is not specified, no glmmod
will be determined
A list of parameters to feed to quality control charts in this package:
call: The call used to obtain output.
data: The data used in the call to the function.
baseline_data: The baseline_data used in the call to the function
glmmod: A glm()
model which can be fed to
the funnel_plot()
and bernoulli_cusum()
functions.
coxphmod: A coxph()
model which can be
fed to the cgr_cusum()
and
cgr_cusum()
functions.
theta: Expected increase in the odds/hazard ratio.
psi: Estimated Poisson arrival rate in data
.
time: Time frame over which to restrict type I error.
alpha: Desired level of type I error for control limit determination.
maxtheta: Maximum expected increase/decrease in the odds/hazard ratio.
Daniel Gomon
require(survival) #Minimal example - no risk-adjustment pars_min <- parameter_assist(baseline_data = surgerydat, data = subset(surgerydat, unit == 1)) #Specifying all parameters pars <- parameter_assist(baseline_data = surgerydat, data = subset(surgerydat, unit == 1), formula = formula("survtime ~ age + sex + BMI"), followup = 100)
require(survival) #Minimal example - no risk-adjustment pars_min <- parameter_assist(baseline_data = surgerydat, data = subset(surgerydat, unit == 1)) #Specifying all parameters pars <- parameter_assist(baseline_data = surgerydat, data = subset(surgerydat, unit == 1), formula = formula("survtime ~ age + sex + BMI"), followup = 100)
Plot a cgrcusum
, bkcusum
,
bercusum
or funnelplot
chart, or a list containing a combination of
'bercusum'
, 'bkcusum'
and 'cgrcusum'
charts.
## S3 method for class 'cgrcusum' plot(x, h, ...) ## S3 method for class 'bkcusum' plot(x, h, ...) ## S3 method for class 'funnelplot' plot(x, percentage = TRUE, unit_label = TRUE, label_size = 3, col_fill = "blue", ...) ## S3 method for class 'bercusum' plot(x, h = x$h, ...)
## S3 method for class 'cgrcusum' plot(x, h, ...) ## S3 method for class 'bkcusum' plot(x, h, ...) ## S3 method for class 'funnelplot' plot(x, percentage = TRUE, unit_label = TRUE, label_size = 3, col_fill = "blue", ...) ## S3 method for class 'bercusum' plot(x, h = x$h, ...)
x |
Chart to plot |
h |
Control limit to display for |
... |
Further plotting parameters |
percentage |
Should output be shown in percentages? Default is |
unit_label |
Should unit labels be displayed next to detected units in the funnel plot?
Default is |
label_size |
Size of the labels when |
col_fill |
Single fill colour for the prediction intervals in the funnel plot.
In any format that |
A plot of the associated chart is displayed in the current graphics device.
plot(cgrcusum)
: Plot a CGR-CUSUM
plot(bkcusum)
: Plot a BK-CUSUM
plot(funnelplot)
: Display a funnel plot
plot(bercusum)
: Plot a Bernoulli CUSUM
Daniel Gomon
cgr_cusum
, bk_cusum
, bernoulli_cusum
, funnel_plot
This function can be used to calculate the run length of a 'cgrcusum', 'bkcusum' or 'bercusum' chart when using control limit h
runlength(chart, h) ## S3 method for class 'cgrcusum' runlength(chart, h, ...) ## S3 method for class 'bkcusum' runlength(chart, h, ...) ## S3 method for class 'bercusum' runlength(chart, h, ...)
runlength(chart, h) ## S3 method for class 'cgrcusum' runlength(chart, h, ...) ## S3 method for class 'bkcusum' runlength(chart, h, ...) ## S3 method for class 'bercusum' runlength(chart, h, ...)
chart |
A |
h |
Control limit h to be used when determining the run length |
... |
Other parameters |
The run length of the chart with the given control limit.
runlength(cgrcusum)
: determines runlength of cgrcusum
object
runlength(bkcusum)
: determines runlength of bkcusum
object
runlength(bercusum)
: determines runlength of bercusum
object
Daniel Gomon
exprfitber <- as.formula("(survtime <= 100) & (censorid == 1) ~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 14), glmmod = glmmodber, followup = 100, theta = log(2)) #Determine the run length of the above Bernoulli CUSUM when using a control limit #of h = 1. runlength(bercus, h = 1)
exprfitber <- as.formula("(survtime <= 100) & (censorid == 1) ~ age + sex + BMI") glmmodber <- glm(exprfitber, data = surgerydat, family = binomial(link = "logit")) bercus <- bernoulli_cusum(data = subset(surgerydat, unit == 14), glmmod = glmmodber, followup = 100, theta = log(2)) #Determine the run length of the above Bernoulli CUSUM when using a control limit #of h = 1. runlength(bercus, h = 1)
Prints a summary of the
funnelplot
object.
## S3 method for class 'funnelplot' summary(object, ...)
## S3 method for class 'funnelplot' summary(object, ...)
object |
S3 object to summarize |
... |
extra parameters |
A data.frame
with:
unit
: unit number/identifier;
observed
: the observed amount of failures at respective unit;
expected
: the expected amount of failures at respective unit,
given that the unit is performing at target;
numtotal
: total number of subjects at respective unit;
p
: estimated probability of failure at unit;
'0.xx'
: better/normal/worse proportion of failure at specified
confidence levels.
summary(funnelplot)
: summarize instances detected by the
funnelplot
object
Data about patients and their surgery procedure from 45 simulated hospitals
with patient arrivals in the first 400 days after the start of the study.
Patient survival times were determined using a risk-adjusted Cox proportional hazards model
with coefficients age = 0.003, BMI = 0.02 and sexmale = 0.2 and exponential baseline hazard rate
.
The increase in hazard rate is sampled from a normal distribution for all hospitals:
This means that the average failure rate of hospitals in the data set
should be baseline (), with some hospitals
experiencing higher and lower failure rates. True failure rate can be found
in the column
exptheta
.
The arrival rate of patients at a hospital differs. The arrival rates are:
Hospitals 1-5 & 16-20: 0.5 patients per day (small hospitals)
Hospitals 6-10 & 21-25: 1 patient per day (medium sized hospitals)
Hospitals 11-15 & 26-30: 1.5 patients per day (large hospitals)
These are then respectively small, medium and large hospitals.
surgerydat
surgerydat
A data.frame
with 12010 rows and 9 variables:
Time of entry of patient into study (numeric)
Time from entry until failure of patient (numeric)
Censoring indicator (0 - right censored, 1 - observed) (integer)
Hospital number at which patient received treatment (integer)
True excess hazard used for generating patient survival (numeric)
Poisson arrival rate at hospital which the patient was at (numeric)
Age of the patient (numeric)
Sex of the patient (factor)
Body mass index of the patient (numeric)
Functions which return the hazard, cumulative
hazard and inverse cumulative hazard at time t for a Weibull distribution
with shape parameter , scale parameter
and true hazard ratio
.
haz_weib(t, lambda, theta, mu = log(1)) chaz_weib(t, lambda, theta, mu = log(1)) inv_chaz_weib(t, lambda, theta, mu = log(1))
haz_weib(t, lambda, theta, mu = log(1)) chaz_weib(t, lambda, theta, mu = log(1)) inv_chaz_weib(t, lambda, theta, mu = log(1))
t |
time of evaluation. |
lambda |
shape parameter |
theta |
scale parameter |
mu |
(optional) true excess hazard rate |
The hazard function of a Weibull distribution is given by:
The cumulative hazard (with true hazard ratio ) is given by:
The inverse cumulative hazard (with true hazard ratio ) by:
Value of specified function at time .