По сути, это вопрос из трех частей:
- Как оценить изменяющиеся во времени эффекты?
- В чем разница между различными спецификациями нестационарных эффектов с использованием функции
survival::coxph
- Как решить, какую форму имеет изменение во времени: линейную, логарифмическую и т. Д.
Я попытаюсь ответить на эти вопросы ниже, используя пример данных ветеранов, который представлен в разделе 4.2 документа виньетка для зависящих от времени ковариат и зависящих от времени коэффициентов (также известных как эффекты, зависящие от времени) в пакете survival
:
library(dplyr)
library(survival)
data("veteran", package = "survival")
veteran <- veteran %>%
mutate(
trt = 1L * (trt == 2),
prior = 1L * (prior == 10))
head(veteran)
#> trt celltype time status karno diagtime age prior
#> 1 0 squamous 72 1 60 7 69 0
#> 2 0 squamous 411 1 70 5 64 1
#> 3 0 squamous 228 1 60 3 38 0
#> 4 0 squamous 126 1 60 9 63 1
#> 5 0 squamous 118 1 70 11 65 1
#> 6 0 squamous 10 1 20 5 49 0
1. Как оценить изменяющиеся во времени эффекты
Существуют разные популярные методы и реализации, например survival::coxph
, timereg::aalen
или с помощью GAM после соответствующего преобразования данных (см. Ниже).
Хотя конкретные методы и их реализации различаются, общая идея состоит в том, чтобы создать длинный набор данных, в котором
- наблюдение разбито на интервалы
- для каждого предмета статус 0 во всех интервалах, кроме последнего (если событие)
- временная переменная обновляется в каждом интервале
Тогда время (или преобразование времени, например, log (t)) - это просто ковариата, и изменяющиеся во времени эффекты могут быть оценены взаимодействием между интересующей ковариатой и (преобразованной) ковариатой времени.
Если функциональная форма изменения времени известна, вы можете использовать tt()
подход:
cph_tt <- coxph(
formula = Surv(time, status) ~ trt + prior + karno + tt(karno),
data = veteran,
tt = function(x, t, ...) x * log(t + 20))
2. В чем разница между различными спецификациями нестационарных эффектов с использованием функции survival::coxph
Нет никакой разницы. Я предполагаю, что функция tt()
- это просто сокращение для оценки через преобразование в длинный формат. Вы можете убедиться, что эти два подхода эквивалентны, используя приведенный ниже код:
преобразовать в длинный формат
veteran_long <- survSplit(Surv(time, status)~., data = veteran, id = "id",
cut = unique(veteran$time)) %>%
mutate(log_time = log(time + 20))
head(veteran_long) %>% select(id, trt, age, tstart, time, log_time, status)
#> id trt age tstart time log_time status
#> 1 1 0 69 0 1 3.044522 0
#> 2 1 0 69 1 2 3.091042 0
#> 3 1 0 69 2 3 3.135494 0
#> 4 1 0 69 3 4 3.178054 0
#> 5 1 0 69 4 7 3.295837 0
#> 6 1 0 69 7 8 3.332205 0
cph_long <- coxph(formula = Surv(tstart, time, status)~
trt + prior + karno + karno:log_time, data = veteran_long)
## models are equivalent, just different specification
cbind(coef(cph_long), coef(cph_tt))
#> [,1] [,2]
#> trt 0.01647766 0.01647766
#> prior -0.09317362 -0.09317362
#> karno -0.12466229 -0.12466229
#> karno:log_time 0.02130957 0.02130957
3. Как решить, какую форму имеет изменение во времени?
Как упоминалось ранее, изменяющиеся во времени эффекты - это просто взаимодействия ковариаты x
и времени t
, поэтому изменяющиеся во времени эффекты могут иметь разные спецификации, эквивалентные взаимодействиям в стандартных регрессионных моделях, например
x*t
: линейный ковариативный эффект, линейно изменяющийся во времени эффект
f(x)*t
: нелинейный ковариантный эффект, линейно изменяющийся во времени эффект
f(t)*x
: линейный ковариантный эффект, нелинейно изменяющийся во времени (для категориального x), по существу представляет собой стратифицированный базовый риск.
f(x, t)
: нелинейный, нелинейно изменяющийся во времени эффект
В каждом случае функциональная форма эффекта f
может быть оценена на основе данных или предварительно определена (например, f(t)*x = karno * log(t + 20)
выше).
В большинстве случаев вы предпочитаете оценивать f
на основе данных. Насколько мне известно, поддержка (штрафной) оценки таких эффектов ограничена пакетом survival
. Однако вы можете использовать mgcv::gam
для оценки любого из указанных выше эффектов (после соответствующего преобразования данных). Пример приведен ниже и показывает, что эффект karno
приближается к 0 с течением времени, независимо от оценки Карновского в начале наблюдения (см. здесь, а также раздел 4.2 здесь):
library(pammtools)
# data transformation
ped <- as_ped(veteran, Surv(time, status)~., max_time = 400)
# model
pam <- mgcv::gam(ped_status ~ s(tend) + trt + prior + te(tend, karno, k = 10),
data = ped, family = poisson(), offset = offset, method = "REML")
p_2d <- gg_tensor(pam)
p_slice <- gg_slice(ped, pam, "karno", tend = unique(tend), karno = c(20, 50, 80), reference = list(karno = 60))
gridExtra::grid.arrange(p_2d, p_slice, nrow = 1)
person
adibender
schedule
09.12.2018