| Title: | Reproducible Assessment of Disability Course in Multiple Sclerosis |
|---|---|
| Description: | Analyse disability course in multiple sclerosis (MS) from longitudinal data. The package provides a flexible framework for identifying disability events under user-specified criteria, allowing adaptation to different study designs and endpoints. Tools are included to facilitate transparent and reproducible reporting of the settings used in the analysis. For an introduction to the package and illustrative applications, see Montobbio et al. (2024) <doi:10.1177/13524585241243157>. |
| Authors: | Noemi Montobbio [aut, cre] (ORCID: <https://orcid.org/0000-0003-0302-393X>), Francesca Bovis [rev], Luca Carmisciano [rev] |
| Maintainer: | Noemi Montobbio <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.0.0 |
| Built: | 2026-06-23 19:16:32 UTC |
| Source: | https://github.com/cran/msprog |
Compute the minimum clinically meaningful score change as a function of the reference value for some widely used scales (EDSS, NHPT, T25FW, or SDMT), according to the most established rule for each of these outcomes.
compute_delta(baseline, outcome = "edss")compute_delta(baseline, outcome = "edss")
baseline |
Outcome value at baseline. |
outcome |
One of:
|
Default thresholds are meant to apply to all versions of each test (e.g., dominant or non-dominant hand for NHPT, best time or mean of two trials, etc.).
Minimum clinically meaningful change from the provided baseline value. Specifically:
EDSS: 1.5 if baseline=0, 1 if 0<baseline<=5.0, 0.5 if baseline>5.0
NHPT and T25FW: 20% of baseline
SDMT: either 4 points or 20% of baseline.
compute_delta(4.5) # default outcome is "edss" compute_delta(55, outcome="sdmt")compute_delta(4.5) # default outcome is "edss" compute_delta(55, outcome="sdmt")
Check if an outcome value determines a valid worsening, or improvement, or change, from a given reference value.
is_event( x, baseline, type, outcome = "edss", worsening = NULL, delta_fun = NULL, sub_threshold = FALSE )is_event( x, baseline, type, outcome = "edss", worsening = NULL, delta_fun = NULL, sub_threshold = FALSE )
x |
Outcome value to test. |
baseline |
Outcome value at baseline. |
type |
One of:
|
outcome |
One of:
Outcome type determines the direction of worsening (see |
worsening |
The direction of worsening ( |
delta_fun |
Custom function specifying the minimum clinically meaningful
change in the outcome measure from the provided reference value.
The function provided must take a numeric value (reference score) as input,
and return a numeric value corresponding to the minimum relevant shift from baseline, see example below.
If |
sub_threshold |
If |
A boolean value specifying if a valid event was found.
is_event(x=4.5, baseline=4, type="wors", outcome="edss") is_event(x=50, baseline=57, type="wors", outcome="sdmt") is_event(x=3, baseline=3.5, type="impr", outcome="edss", sub_threshold=TRUE)is_event(x=4.5, baseline=4, type="wors", outcome="edss") is_event(x=50, baseline=57, type="wors", outcome="sdmt") is_event(x=3, baseline=3.5, type="impr", outcome="edss", sub_threshold=TRUE)
Detect and characterise confirmed disability worsening (CDW) or improvement (CDI) events of an outcome measure (EDSS, NHPT, T25FW, or SDMT; or any custom outcome) based on repeated assessments through time (and on the dates of acute episodes, if any). The events are detected sequentially by scanning the outcome values in chronological order. Several qualitative and quantitative options are given as arguments that can be set by the user and reported as a complement to the results to ensure reproducibility.
MSprog( data, subj_col, value_col, date_col, outcome, relapse = NULL, rsubj_col = NULL, rdate_col = NULL, renddate_col = NULL, subjects = NULL, delta_fun = NULL, worsening = NULL, event = c("firstCDW", "firstCDI", "multiple", "firstPIRA", "firstRAW", "first"), RAW_PIRA = FALSE, baseline = c("fixed", "roving", "roving_impr", "roving_wors"), proceed_from = c("firstconf", "event"), sub_threshold_rebl = c("none", "change", "improvement", "worsening"), bl_geq = FALSE, relapse_rebl = FALSE, skip_local_extrema = c("none", "strict", "all"), validconf_col = NULL, conf_days = 12 * 7, conf_tol_days = c(7, 2 * 365.25), require_sust_days = 0, check_intermediate = TRUE, relapse_to_bl = 30, relapse_to_event = 0, relapse_to_conf = 30, relapse_assoc = 90, relapse_indep = NULL, impute_last_visit = 0, date_format = NULL, include_dates = FALSE, include_values = FALSE, include_stable = TRUE, verbose = 1 )MSprog( data, subj_col, value_col, date_col, outcome, relapse = NULL, rsubj_col = NULL, rdate_col = NULL, renddate_col = NULL, subjects = NULL, delta_fun = NULL, worsening = NULL, event = c("firstCDW", "firstCDI", "multiple", "firstPIRA", "firstRAW", "first"), RAW_PIRA = FALSE, baseline = c("fixed", "roving", "roving_impr", "roving_wors"), proceed_from = c("firstconf", "event"), sub_threshold_rebl = c("none", "change", "improvement", "worsening"), bl_geq = FALSE, relapse_rebl = FALSE, skip_local_extrema = c("none", "strict", "all"), validconf_col = NULL, conf_days = 12 * 7, conf_tol_days = c(7, 2 * 365.25), require_sust_days = 0, check_intermediate = TRUE, relapse_to_bl = 30, relapse_to_event = 0, relapse_to_conf = 30, relapse_assoc = 90, relapse_indep = NULL, impute_last_visit = 0, date_format = NULL, include_dates = FALSE, include_values = FALSE, include_stable = TRUE, verbose = 1 )
data |
Data frame containing longitudinal data, including: subject IDs, outcome values, visit dates. |
subj_col |
Name of data column with subject IDs. |
value_col |
Name of data column with outcome values. |
date_col |
Name of data column with visit dates. |
outcome |
Specifies the outcome type. Must be one of the following:
When it's not set to |
relapse |
Optional data frame containing longitudinal data, including subject IDs and relapse onset dates. |
rsubj_col |
Name of subject ID column in the |
rdate_col |
Name of relapse onset date column in the |
renddate_col |
Name of relapse end date column in the |
subjects |
Subset of subjects (a vector or list of IDs). If none is specified, all subjects listed in |
delta_fun |
Custom function specifying the minimum clinically meaningful
change in the outcome measure from the provided reference value.
The function provided must take a numeric value (reference score) as input,
and return a numeric value corresponding to the minimum shift from baseline, see example below.
If |
worsening |
The direction of worsening ( The given value is only used when |
event |
Character string specifying which events to detect. Must be one of the following.
|
RAW_PIRA |
If |
baseline |
Specifies the baseline scheme. Must be one of the following.
|
proceed_from |
After detecting a confirmed disability event, continue searching:
If
|
sub_threshold_rebl |
This argument is only used if
See |
bl_geq |
This argument is only used if relapse-based re-baseline is enabled ( |
relapse_rebl |
If |
skip_local_extrema |
This argument is only used if the baseline is moved. It controls re-baseline behaviour in the presence of local minima or maxima. A visit
Local maxima are defined similarly. A visit
Strict local maxima are defined similarly. When
|
validconf_col |
Name of data column, if any, specifying which visits can
( |
conf_days |
Period before confirmation (days). Can be a single value, or
vector of any length if considering multiple windows.
If |
conf_tol_days |
Tolerance window for confirmation visit (days).
Can be an integer (equal lower and upper tolerance)
or vector of length 2 (different lower and upper tolerance).
The right end of the interval (upper tolerance) may be set to |
require_sust_days |
Minimum number of days over which a confirmed change must be sustained
(i.e., confirmed at all visits occurring in the specified period) to be retained as an event.
Events sustained for the remainder of the follow-up period are always retained regardless of follow-up duration.
If (Warning: if |
check_intermediate |
If If set to |
relapse_to_bl |
Minimum distance (days) from the onset of a relapse for a visit to be used as baseline. Can be an integer (minimum distance from last relapse onset) or vector of length 2 (minimum distance from last relapse onset, minimum distance from next relapse onset). Note that setting the distance to zero means keeping the baseline where it is regardless of surrounding relapses. If relapse end dates are available ( If the designated baseline does not satisfy this constraint, the baseline is moved to the next available visit. |
relapse_to_event |
Minimum distance (days) from the onset of a relapse for an event to be considered as such. Can be an integer (minimum distance from last relapse onset) or vector of length 2 (minimum distance from last relapse onset, minimum distance from next relapse onset). Note that setting the distance to zero means retaining the event regardless of surrounding relapses. If relapse end dates are available ( |
relapse_to_conf |
Minimum distance (days) from the onset of a relapse for a visit to be an eligible confirmation visit. Can be an integer (minimum distance from last relapse onset) or vector of length 2 (minimum distance from last relapse onset, minimum distance from next relapse onset). Note that setting the distance to zero means using any visit for confirmation regardless of surrounding relapses. If relapse end dates are available ( |
relapse_assoc |
Maximum distance (days) from the onset of a relapse for a CDW event to be classified as RAW.
Can be an integer (maximum distance from last relapse onset) or vector of length 2
(maximum distance from last relapse onset, maximum distance from next relapse onset).
If relapse end dates are available ( |
relapse_indep |
Specifies relapse-free intervals for PIRA definition.
Must be a named list
The auxiliary function |
impute_last_visit |
Imputation probability for worsening events occurring
at the last available visit (i.e., with no confirmation).
Unconfirmed worsening events occurring at the last visit are never imputed if |
date_format |
Format of dates in the
If not specified, function |
include_dates |
If
|
include_values |
If
|
include_stable |
If |
verbose |
One of:
|
An object of class MSprogOutput with the following attributes:
event_count: a data frame containing event counts for each subject
(and the event sequence in case of multiple events).
results: a data frame with extended info on each event for all subjects.
settings: a list containing all the arguments used to compute the output.
unconfirmed: a data frame with info on unconfirmed events (initial change from baseline, but no confirmation)
for all subjects.
For a detailed description of output data frames, see ?MSprogOutput.
[1] Müller J, Cagol A, Lorscheider J, Tsagkas C, Benkert P, Yaldizli Ö, et al.
Harmonizing definitions for progression independent of relapse activity in multiple sclerosis: A systematic review.
JAMA Neurol. 2023;80:1232–45.
[2] Kappos L, Wolinsky JS, Giovannoni G, Arnold DL, Wang Q, Bernasconi C, et al.
Contribution of relapse-independent progression vs relapse-associated worsening to overall confirmed disability
accumulation in typical relapsing multiple sclerosis in a pooled analysis of 2 randomized clinical trials.
JAMA Neurol. 2020;77:1132–40.
# 1. EDSS course output <- MSprog(toydata_visits, subj_col="id", value_col="EDSS", date_col="date", outcome="edss", relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject # 2. SDMT course output <- MSprog(toydata_visits, subj_col="id", value_col="SDMT", date_col="date", outcome="sdmt", relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject # 3. SDMT course, with a custom delta function my_sdmt_delta <- function(reference_value) {min(c(reference_value/10, 3))} output <- MSprog(toydata_visits, subj_col="id", value_col="SDMT", date_col="date", outcome="sdmt", delta_fun=my_sdmt_delta, relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject# 1. EDSS course output <- MSprog(toydata_visits, subj_col="id", value_col="EDSS", date_col="date", outcome="edss", relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject # 2. SDMT course output <- MSprog(toydata_visits, subj_col="id", value_col="SDMT", date_col="date", outcome="sdmt", relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject # 3. SDMT course, with a custom delta function my_sdmt_delta <- function(reference_value) {min(c(reference_value/10, 3))} output <- MSprog(toydata_visits, subj_col="id", value_col="SDMT", date_col="date", outcome="sdmt", delta_fun=my_sdmt_delta, relapse=toydata_relapses, conf_days=12*7, conf_tol_days=30, event="multiple", baseline="roving", verbose=1) print(output$results) # extended info on each event for all subjects print(output$event_count) # event counts for each subject
print method for class "MSprogOutput".
## S3 method for class 'MSprogOutput' print(x, ...)## S3 method for class 'MSprogOutput' print(x, ...)
x |
An object of class |
... |
Optional arguments for |
The method prints out (1) the package version, (2) a full list of function arguments, and (3) a short paragraph describing the full set of criteria used to obtain the output.
Invisibly returns x.
output <- MSprog(toydata_visits, "id", "EDSS", "date", "edss", relapse=toydata_relapses, conf_days=7*12, conf_tol_days=30, event="multiple", baseline="roving", verbose=2) print(output) # textual description of parameters used to obtain outputoutput <- MSprog(toydata_visits, "id", "EDSS", "date", "edss", relapse=toydata_relapses, conf_days=7*12, conf_tol_days=30, event="multiple", baseline="roving", verbose=2) print(output) # textual description of parameters used to obtain output
Organise the given interval bounds into a named list to be given as argument
relapse_indep to function MSprog().
The relapse-free intervals may be anchored to (any subset of) the following
three data-driven checkpoints.
"prec": a visit preceding the event: can be (i) the current baseline, (ii) the last visit before event onset,
or (iii) the last visit before event onset with a clinically meaningful score difference from it
(i.e., for an outcome x with "higher score" = "worse", the last visit i such that x[event] - x[i] >= delta_fun(x[i]),
and same for the confirmation visit).
"event": the disability worsening event onset.
"conf": an eligible confirmation visit.
relapse_indep_from_bounds( p0 = 0, p1 = 0, e0 = 0, e1 = 0, c0 = 0, c1 = 0, prec_type = "baseline", use_end_dates = F )relapse_indep_from_bounds( p0 = 0, p1 = 0, e0 = 0, e1 = 0, c0 = 0, c1 = 0, prec_type = "baseline", use_end_dates = F )
p0 |
Days before preceding visit ( |
p1 |
Days after preceding visit ( |
e0 |
Days before event onset ( |
e1 |
Days after event onset ( |
c0 |
Days before confirmation ( |
c1 |
Days after confirmation ( |
prec_type |
Which visit to use as "preceding visit". Must be one of:
|
use_end_dates |
If |
If both ends of an interval are 0 (e.g., if both p0=0 and p1=0), the checkpoint is ignored.
To merge two intervals together, set both the right end of the first interval and the left end of the
second interval to NULL (e.g., "between baseline and event onset": p1=NULL and e0=NULL).
Here are some examples:
No relapses from 90dd before to 30dd after the event, and from 90dd before to 30dd after confirmation [1]:
relapse_indep_from_bounds(e0=90,e1=30,c0=90,c1=30).
No relapses between baseline and confirmation (high-specificity definition from [1]):
relapse_indep_from_bounds(p0=0,p1=NULL,e0=NULL,e1=NULL,c0=NULL,c1=0).
No relapses from baseline to 30dd after the event, and within confirmation+-30dd [2]:
relapse_indep_from_bounds(p0=0,p1=NULL,e0=NULL,e1=30,c0=30,c1=30).
A named list to be given as argument relapse_indep to function MSprog().
[1] Müller J, Cagol A, Lorscheider J, Tsagkas C, Benkert P, Yaldizli Ö, et al.
Harmonizing definitions for progression independent of relapse activity in multiple sclerosis: A systematic review.
JAMA Neurol. 2023;80:1232–45.
[2] Kappos L, Wolinsky JS, Giovannoni G, Arnold DL, Wang Q, Bernasconi C, et al.
Contribution of relapse-independent progression vs relapse-associated worsening to overall confirmed disability
accumulation in typical relapsing multiple sclerosis in a pooled analysis of 2 randomized clinical trials.
JAMA Neurol. 2020;77:1132–40.
Artificially generated relapse onset dates for some example patients in toydata_visits to illustrate the use of the package.
data(toydata_relapses)data(toydata_relapses)
An object of class data.frame, with columns:
Subject IDs.
Relapse onset dates.
This data set was artificially created for the msprog package.
data(toydata_relapses) head(toydata_relapses)data(toydata_relapses) head(toydata_relapses)
Artificially generated toy data set including Extended Disability Status Scale (EDSS) and Symbol Digit Modalities Test (SDMT) scores in a small cohort of example patients to illustrate the use of the package.
data(toydata_visits)data(toydata_visits)
An object of class data.frame, with columns:
Subject IDs.
Visit dates.
Synthetic EDSS scores (values between 0 and 10).
Synthetic SDMT scores (values between 0 and 110).
This data set was artificially created for the msprog package.
head(toydata_visits)head(toydata_visits)
Scan the visits in chronological order to detect the first outcome value reaching or exceeding a specified disability milestone (e.g., EDSS>=6), with confirmation.
value_milestone( data, milestone, subj_col, value_col, date_col, outcome, worsening = NULL, relapse = NULL, rsubj_col = NULL, rdate_col = NULL, validconf_col = NULL, conf_days = 12 * 7, conf_tol_days = c(7, 2 * 365.25), require_sust_days = 0, relapse_to_event = 0, relapse_to_conf = 30, impute_last_visit = 0, date_format = NULL, verbose = 0 )value_milestone( data, milestone, subj_col, value_col, date_col, outcome, worsening = NULL, relapse = NULL, rsubj_col = NULL, rdate_col = NULL, validconf_col = NULL, conf_days = 12 * 7, conf_tol_days = c(7, 2 * 365.25), require_sust_days = 0, relapse_to_event = 0, relapse_to_conf = 30, impute_last_visit = 0, date_format = NULL, verbose = 0 )
data |
Data frame containing longitudinal data, including: subject IDs, outcome values, visit dates. |
milestone |
Disability milestone (outcome value to check data against). |
subj_col |
Name of data column with subject IDs. |
value_col |
Name of data column with outcome values. |
date_col |
Name of data column with visit dates. |
outcome |
Specifies the outcome type. Must be one of the following:
When it's not set to |
worsening |
The direction of worsening ( |
relapse |
Optional data frame containing longitudinal data, including subject IDs and relapse onset dates. |
rsubj_col |
Name of subject ID column in the |
rdate_col |
Name of date column in the |
validconf_col |
Name of data column, if any, specifying which visits can
( |
conf_days |
Period before confirmation (days). Can be a single value, or
vector of any length if considering multiple windows.
If |
conf_tol_days |
Tolerance window for confirmation visit (days); can be
an integer (equal lower and upper tolerance)
or vector of length 2 (different lower and upper tolerance).
The right end of the interval can be set to |
require_sust_days |
Minimum number of days over which the milestone must be sustained
(i.e., confirmed at all visits occurring in the specified period).
If the milestone is sustained for the remainder of the follow-up period, it is considered reached regardless of follow-up duration.
If |
relapse_to_event |
Minimum distance (days) from the onset of a relapse for the milestone to be considered reached. Can be an integer (minimum distance from last relapse onset) or vector of length 2 (minimum distance from last relapse onset, minimum distance from next relapse onset). Note that setting the distance to zero means retaining the event regardless of surrounding relapses. |
relapse_to_conf |
Minimum distance (days) from the onset of a relapse for a visit to be a valid confirmation visit. Can be an integer (minimum distance from last relapse onset) or vector of length 2 (minimum distance from last relapse onset, minimum distance from next relapse onset). Note that setting the distance to zero means using any visit for confirmation regardless of surrounding relapses. |
impute_last_visit |
Imputation probability when the milestone is reached
at the last available visit (i.e., with no confirmation).
Unconfirmed values exceeding the milestone at the last visit are never imputed
if |
date_format |
Format of dates in the
If not specified, function |
verbose |
One of:
|
"Reaching or exceeding" means either value>=milestone or value<=milestone, depending on the
direction of worsening (see arguments outcome and worsening).
An event is only considered "observed" if confirmed, i.e., if all values up to the confirmation visit reach or exceed the milestone.
A data frame containing the following columns:
<date_col>: the date of first reaching or exceeding the milestone with confirmation
(or last date of follow-up if milestone is not reached or not confirmed).
<value_col: the first value reaching or exceeding the milestone with confirmation,
if present, otherwise no value.
"time2event": the time taken to reach or exceed the milestone (or total
follow-up length if milestone is not reached or not confirmed).
"observed": whether the milestone was reached with confirmation (1) or not (0).