knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
See Magirr and Burman (2019) and Magirr (2021) for details about the weighted log-rank tests, and in particular the modestly weighted log-rank test. This vignette works through an example of using the package to simulate data and perform weighted log-rank tests. A summary of the formulas used within this package is presented.
This package can be used to simulate a dataset for a two-arm RCT with delayed separation of survival curves by using the sim_events_delay
function.
There are two parts to simulating the event times and statuses: the event model (parameters defined in event_model
) and the recruitment model (parameters defined in recruitment_model
).
Firstly, looking at the event model. The function sim_events_delay
assumes that the survival times on the control and exponential arm follow a piecewise exponential distribution. Given rate parameter $\lambda$, the exponential distribution has the form:
[ f(t)=\lambda \exp(-\lambda t) ]
The rate parameters are set using the argument lambda_c
for the control arm and lambda_e
for the experimental arm. To use the piecewise version, set this argument a vector with a value for each piece. The duration of each piece is set using parameter duration_c
and duration_e
.
Secondly, looking at the recruitment model. The recruitment can be modeled using either a power model or a piecewise constant model. See help(sim_events_delay)
more details about these models.
Additionally, the sim_events_delay
function censors all observations at the calendar time max_cal_t
.
Here we create a simulated dataset with 5 individuals on each arm. Assume that one unit of time is equal to one month. From entering the study until 6 months both arms have the same $\lambda$ parameter, with a median event time of 9 months. From 6 months, the experimental arm has a lower hazard rate, with a median event time of 18 months. Setting rec_period = 12
and rec_power = 1
means that individuals are recruited at a uniform rate over 12 months.
library(nphRCT) set.seed(1) sim_data <- sim_events_delay( event_model=list( duration_c = 36, duration_e = c(12 ,24), lambda_c = log(2)/9, lambda_e = c(log(2)/9,log(2)/18)), recruitment_model=list( rec_model="power", rec_period=12, rec_power=1), n_c=5, n_e=5, max_cal_t = 36 ) sim_data
Now that we have simulated a dataset, we will look at performing the weighted log-rank tests.
Consider the ordered, distinct event times $t_1, \dots, t_k$. Let $d_{0,j}$ and $d_{1,j}$ be the number of events at event time $t_{j}$ on each of the arms respectively, and let $d_{j}$ be equal to the sum of these two values. Similarly, let $n_{0,j}$ and $n_{1,j}$ be the number at risk at event time $t_{j}$ on each of the arms respectively, and let $n_{j}$ be equal to the sum of these two values.
The function find_at_risk
can be used to calculate these values for a dataset.
find_at_risk(formula=Surv(event_time,event_status)~group, data=sim_data, include_cens=FALSE)
Here, each row relates to the distinct event times $t_j$, which are specified in column t_j
. The value $d_{0,j}$ relates to the column n_event_control
, $d_{1,j}$ to n_event_experimental
, and $d_{j}$ to n_event
. Similarly, $n_{0,j}$ relates to column n_risk_control
, $n_{1,j}$ to n_risk_experimental
, and $n_{j}$ to n_risk
.
To calculate the test statistics for a weighted log-rank test, we need to evaluate the observed number of events on one arm, e.g. $d_{0,j}$, and the expected number of events on the same arm, e.g. $d_j \frac{n_{0,j}}{n_j}$ at each $t_j$. The test statistic $U^W$ is then a weighted sum (using weights $w_j$) of the difference of these values:
[ U^W = \sum_{j=1}^k w_j \left(d_{0,j} - d_j \frac{n_{0,j}}{n_j}\right) ]
The weights $w_j$ that are used depend on the type of weighted log-rank test, these are described next.
Three types of weighted log rank test are available in this package.
The values of the weights in the log-rank test can be calculated using the function find_weights
with argument method="lr"
. In the case of the standard log-rank test, the weights are clearly very simple.
find_weights(formula=Surv(event_time,event_status)~group, data=sim_data, method="lr", include_cens = FALSE)
Again the weights can be calculated using the find_weights
function and setting method="fh"
, along with arguments rho
and gamma
.
find_weights(formula=Surv(event_time,event_status)~group, data=sim_data, method="fh", rho = 0, gamma= 1, include_cens = FALSE)
find_weights(formula=Surv(event_time,event_status)~group, data=sim_data, method="mw", s_star = 0.5, include_cens = FALSE)
Under the null hypothesis that the survival curves of the two treatment arms are equal, the distribution of $U^W$ is
[ U^W \sim N\left( 0, V^W \right) ]
where the variance, $V^W$, is equal to [ \sum_{j=1}^k w_j^2\frac{n_{0,j}n_{1,j} d_j (n_j - d_j)}{n_j^2(n_j-1)} ]
The Z-statistic is then simply calculated in the usual way by dividing the test statistic $U$ by the square root of its variance.
To perform the full weighted log-rank test, use the function wlrt
. This outputs the test statistic, its variance, the Z-statistic and the name of the treatment group the test corresponds to.
wlrt(formula=Surv(event_time,event_status)~group, data=sim_data, method="mw", s_star = 0.5)
Leton and Zuluaga (2001) showed that every weighted log-rank test can be written as either an observed-minus-expected test (as described above), or as a permutation test.
The weights can be reformulated as scores for a permutation test using the following formula for the censoring scores and event scores respectively:
[ C_j=-\sum_{i=1}w_i\frac{d_i}{n_i} ]
[ c_j=C_j+w_j ]
These scores can be calculated using the function find_scores
in the following way. Plotting these scores against the rank of the event times provides an intuitive explanation of the issues of using the Fleming-Harrington test as it makes sense that the scores for the events are decreasind with time, see Magirr (2021).
df_scores_mw<-find_scores(formula=Surv(event_time,event_status)~group, data=sim_data, method="mw", s_star = 0.5) plot(df_scores_mw) df_scores_fh<-find_scores(formula=Surv(event_time,event_status)~group, data=sim_data, method="fh", rho = 0, gamma=1) plot(df_scores_fh)
The issue of stratification when performing weighted log-rank tests is discussed in Magirr and Jiménez (2022). They explore various approaches to combining the results of stratified analyses. In particular they recommend combining on the Z-statistic scale, i.e. for the case of two strata, first express the stratified log-rank test as a linear combination of standardized Z-statistics, $\sqrt{V_1}Z_1+\sqrt{V_2}Z_2 \sim N(0,V_1+V_2)$. $V_1$ and $V_2$ are the variances for the log-rank test statistic on the first and second stratum respectively, and $Z_1$ and $Z_2$ are the Z-statistics for the log-rank test statistic on the first and second stratum respectively. Secondly, the Z-statistics $Z_1$ and $Z_2$ are replaced by the Z-statistics from the weighted log-rank test.
[ \tilde{U}^W=\sqrt{V_1}\left( \frac{U_1^W}{\sqrt{V_1^W}}\right)+\sqrt{V_2}\left( \frac{U_2^W}{\sqrt{V_2^W}}\right) ]
Here we introduce a strata ecog
that has different $\lambda$ parameters, and demonstrate that it is simple to perform the described stratified weighted log-rank test.
sim_data_0 <- sim_data sim_data_0$ecog=0 sim_data_1 <- sim_events_delay( event_model=list( duration_c = 36, duration_e = c(6,30), lambda_c = log(2)/6, lambda_e = c(log(2)/6,log(2)/12)), recruitment_model=list( rec_model="power", rec_period=12, rec_power=1), n_c=5, n_e=5, max_cal_t = 36 ) sim_data_1$ecog=1 sim_data_strata<-rbind(sim_data_0,sim_data_1) wlrt(formula=Surv(event_time,event_status)~group+strata(ecog), data=sim_data_strata, method="mw", t_star = 4 )
Leton, E. and Zuluaga, P. (2001) Equivalence between score and weighted tests for survival curves. Commun Stat., 30(4), 591-608.
Magirr, D. (2021). Non-proportional hazards in immuno-oncology: Is an old perspective needed?. Pharmaceutical Statistics, 20(3), 512-527.
Magirr, D. and Burman, C.F., (2019). Modestly weighted logrank tests. Statistics in medicine, 38(20), 3782-3790.
Magirr, D. and Jiménez, J. (2022) Stratified modestly-weighted log-rank tests in settings with an anticipated delayed separation of survival curves PREPRINT at https://arxiv.org/abs/2201.10445
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.