TTM

TTM R package for terminal trend model.

Overview

The TTM package fits a retrospective-time longitudinal model for outcomes measured before death using weighted generalized estimating equations (WGEE). The main idea is to model the longitudinal outcome on a retrospective time scale,

\[ Y = \beta_\mu(t^\*) + A \times \beta_A(t^\*) + \beta_X^T X + \epsilon, \]

where \(t^*\) is the retrospective time, \(A\) is a treatment indicator, \(X\) are baseline covariates, and \(\epsilon\) is a random error term. The retrospective time is defined as

\[ t^* = \mathrm{OS\_time} - \mathrm{t\_pros}, \]

where \(\mathrm{OS\_time}\) is the observed survival time and \(\mathrm{t\_pros}\) is the prospective measurement time. This makes it natural to study how a longitudinal outcome changes as a subject approaches death.

The package supports two model interfaces:

The target trajectories are:

The weighted GEE step uses inverse-probability-type weights built from a Cox dropout model and censoring information, and uncertainty is estimated using delete-group jackknife replicates.

Data structure

The input data should be in long format, with one row per subject-visit. Each row should include:

The event variable is assumed to be coded as:

Example dataset

The package includes a long-format example dataset:

library(TTM)

data("TTM_data", package = "TTM")

A typical analysis uses:

Main fitting function: TTM()

The default entry point is TTM(). It fits a retrospective-time model using a natural-spline basis for time and selects the number of internal knots from n_inner_knot_list using the supplied model-selection criterion.

The original TTM() implementation is the package’s primary model-fitting function. It begins by cleaning the long-format data and constructing retrospective time as \(t^* = \mathrm{OS\_time} - \mathrm{t\_pros}\). It then fits a Cox model for dropout, computes the corresponding subject-level weights, and uses a weighted GEE among observations from subjects with observed death events to estimate the baseline trajectory \(\beta_\mu(t^*)\) and the treatment effect trajectory \(\beta_A(t^*)\). Uncertainty is obtained with delete-group jackknife replicates.

The most important arguments are:

fit <- TTM(data_long = TTM_data,
                                id = "id",
                                treatment = "A",
                                outcome = "Y",
                                covariates = c("X1", "X2"),
                                os_time = "OS_time",
                                event = "event",
                                t_pros = "t_pros",
                                jk_block_size = NULL,
                                n_inner_knot_list = range(10),
                                corstr = "ar1",
                                criteria = "RJC")

Difference between TTM() and TTM_linear()

The two functions share the same overall objective and weighting framework, but they differ in the spline specification:

In other words, TTM() is the more general original implementation, while TTM_linear() is a streamlined version built on the same retrospective-time model structure.

The function returns a list with components such as:

The weighted GEE results are stored in fit$weighted_gee, including:

Linear-spline variant: TTM_linear()

TTM_linear() is a lower-dimensional alternative that constructs a spline basis using a linear spline representation. This can be useful when a simpler basis is desired or when you want to specify knots directly rather than using the automatic knot-selection procedure in TTM().

fit_linear <- TTM_linear(
    data_long = TTM_data,
    id = "id",
    treatment = "A",
    outcome = "Y",
    covariates = c("X1", "X2"),
    os_time = "OS_time",
    event = "event",
    t_pros = "t_pros",
    knots = 6,
    jk_block_size = NULL,
    corstr = "ar1",
    spline_type = "bs"
)

TTM_linear() has the same overall structure as TTM() but stores additional information such as:

This is a convenient option when the main interest is a simpler retrospective-time specification while still using the same weighting and jackknife framework.

Extracting trajectory estimates

Once a model has been fit, the estimated retrospective trajectories can be evaluated at specific time points with get_beta_mu() and get_beta_A().

To evaluate the baseline trajectory \(\beta_\mu(t^*)\) at selected retrospective times:

get_beta_mu(new_times = 1:10, results = fit, conf.level = 0.95)

To evaluate the treatment-effect trajectory \(\beta_A(t^*)\) at selected retrospective times:

get_beta_A(new_times = 1:10, results = fit, conf.level = 0.95)

The same functions also work for TTM_linear() results, because the helper functions reconstruct the appropriate spline basis from the fitted object.

These functions return a list containing the evaluated time grid, estimated trajectory, pointwise standard error, and lower/upper confidence limits.

Visualization

The package includes plotting functions for the fitted retrospective trajectories.

To plot the estimated baseline trajectory \(\beta_\mu(t^*)\) with pointwise confidence intervals:

plot_beta_mu(results = fit, conf.level = 0.95)

To plot the estimated treatment-effect trajectory \(\beta_A(t^*)\) with pointwise confidence intervals:

plot_beta_A(results = fit, conf.level = 0.95)

The same plotting functions can be used with fit_linear as well:

plot_beta_mu(results = fit_linear, conf.level = 0.95)
plot_beta_A(results = fit_linear, conf.level = 0.95)

Test slope difference for TTM_linear() object

Test the difference in the slope of \(\beta_\mu(t^*)\) between and after the specified knots. new_times should be a vector of three retrospective times, where the first one is before the knot and the last is after the knot. The middle one is the knot in the TTM_linear() function.

test_beta_slope(new_times = c(5, 6, 7), fit = fit_linear, var_name = "X0")

Test the difference in the slope of \(\beta_A(t^*)\) between and after the specified knots.

test_beta_slope(new_times = c(5, 6, 7), fit = fit_linear, var_name = "A")

Summary

The package provides two complementary retrospective-time model fits:

Both approaches estimate treatment and baseline retrospective trajectories using weighted GEE and return trajectory summaries and plots through the helper functions in the package.