Коефіцієнти, залежні від часу в R - як це зробити?


17

Оновлення : Вибачте за інше оновлення, але я знайшов можливі рішення з дробовими поліномами та конкуруючим пакетом ризиків, з яким мені потрібна допомога.


Проблема

Я не можу знайти простий спосіб зробити залежний від часу аналіз коефіцієнтів в Р. Я хочу, щоб я міг взяти свій коефіцієнт змінних і зробити це в залежно від часу коефіцієнта (не змінної), а потім побудувати зміни в залежності від часу:

βму_vаriабле=β0+β1т+β2т2...

Можливі рішення

1) Розбиття набору даних

Я розглянув цей приклад (Se частина 2 лабораторного сеансу), але створення окремого набору даних здається складним, обчислювально дорогим і не дуже інтуїтивним ...

2) Моделі зі зниженим рейтингом - пакет coxvc

Пакет coxvc забезпечує елегантний спосіб вирішення проблеми - ось посібник . Проблема полягає в тому, що автор більше не розробляє пакунок (остання версія починається з 23.05.2007), після розмови електронною поштою я змусив цей пакет працювати, але один запуск займав 5 годин на моєму наборі даних (140 000 записи) і дає крайні оцінки в кінці періоду. Ви можете знайти трохи оновлений пакет тут - я здебільшого лише оновив функцію сюжету.

Це може бути лише питанням налаштування, але оскільки програмне забезпечення не забезпечує легких інтервалів довіри, і процес настільки трудомісткий, я зараз шукаю інші рішення.

3) Пакет таймрег

Вражаючий пакет timereg також вирішує проблему, але я не впевнений у тому, як її використовувати, і це не дає мені чіткої картини .

4) Модель дробового полінома (FPT)

Я знайшов відмінну дисертацію Аніки Буххольц на тему "Оцінка часових ефектів терапії та прогностичних факторів, що залежать від часу" , і це чудова робота, що охоплює різні моделі. Вона робить висновок, що пропонований FPT Sauerbrei та ін є найбільш підходящим для залежних від часу коефіцієнтів:

FPT дуже добре виявляє ефекти, що змінюються у часі, тоді як підхід Reduced Rank призводить до занадто складних моделей, оскільки він не включає вибір ефектів, що змінюються за часом.

Дослідження здається дуже повним, але для мене воно трохи недосяжне. Мені теж мало цікаво, оскільки вона трапляється працювати з Sauerbrei. Це здається здоровим, і я думаю, що аналіз можна зробити з пакетом mfp, але я не знаю як.

5) Пакет cmprsk

Я думав робити свій конкурентний аналіз ризику, але розрахунки були трудомісткими, тому я перейшов на регулярну регресію Кокса. У CRR є варіант для коваріатів, залежних від часу:

....
cov2        matrix of covariates that will be multiplied 
            by functions of time; if used, often these 
            covariates would also appear in cov1 to give 
            a prop hazards effect plus a time interaction
....

Є квадратичний приклад, але я не зовсім слідую, де насправді з’являється час, і я не знаю, як його відобразити. Я також подивився файл test.R, але приклад там в основному той самий ...

Мій приклад код

Ось приклад, який я використовую для тестування різних можливостей

library("survival")
library("timereg")
data(sTRACE)

# Basic cox regression    
surv <- with(sTRACE, Surv(time/365,status==9))
fit1 <- coxph(surv~age+sex+diabetes+chf+vf, data=sTRACE)
check <- cox.zph(fit1)
print(check)
plot(check, resid=F)
# vf seems to be the most time varying

######################################
# Do the analysis with the code from #
# the example that I've found        #
######################################

# Split the dataset according to the splitSurv() from prof. Wesley O. Johnson
# http://anson.ucdavis.edu/~johnson/st222/lab8/splitSurv.ssc
new_split_dataset = splitSuv(sTRACE$time/365, sTRACE$status==9, sTRACE[, grep("(age|sex|diabetes|chf|vf)", names(sTRACE))])

surv2 <- with(new_split_dataset, Surv(start, stop, event))
fit2 <- coxph(surv2~age+sex+diabetes+chf+I(pspline(stop)*vf), data=new_split_dataset)
print(fit2)

######################################
# Do the analysis by just straifying #
######################################
fit3 <- coxph(surv~age+sex+diabetes+chf+strata(vf), data=sTRACE)
print(fit3)

# High computational cost!
# The price for 259 events
sum((sTRACE$status==9)*1)
# ~240 times larger dataset!
NROW(new_split_dataset)/NROW(sTRACE)

########################################
# Do the analysis with the coxvc and   #
# the timecox from the timereg library #
########################################
Ft_1 <- cbind(rep(1,nrow(sTRACE)),bs(sTRACE$time/365,df=3))
fit_coxvc1 <- coxvc(surv~vf+sex, Ft_1, rank=2, data=sTRACE)

fit_coxvc2 <- coxvc(surv~vf+sex, Ft_1, rank=1, data=sTRACE)

Ft_3 <- cbind(rep(1,nrow(sTRACE)),bs(sTRACE$time/365,df=5))
fit_coxvc3 <- coxvc(surv~vf+sex, Ft_3, rank=2, data=sTRACE)

layout(matrix(1:3, ncol=1))
my_plotcoxvc <- function(fit, fun="effects"){
    plotcoxvc(fit,fun=fun,xlab='time in years', ylim=c(-1,1), legend_x=.010)
    abline(0,0, lty=2, col=rgb(.5,.5,.5,.5))
    title(paste("B-spline =", NCOL(fit$Ftime)-1, "df and rank =", fit$rank))
}
my_plotcoxvc(fit_coxvc1)
my_plotcoxvc(fit_coxvc2)
my_plotcoxvc(fit_coxvc3)

# Next group
my_plotcoxvc(fit_coxvc1)

fit_timecox1<-timecox(surv~sex + vf, data=sTRACE)
plot(fit_timecox1, xlab="time in years", specific.comps=c(2,3))

Код приводить до цих графіків: Порівняння різних параметрів для coxvc та coxvc та графіків timecox . Я думаю, що результати нормальні, але я не думаю, що мені вдасться пояснити графік timecox - він здається складним ...

Мої (поточні) запитання

  • Як мені зробити аналіз FPT в R?
  • Як я можу використовувати часовий коефіцієнт у cmprsk?
  • Як побудувати результат (бажано з довірчими інтервалами)?

3
у=хβмуу=хβ0+хтβ1+хт2β2y~xy~x*(t+t^2)-ty~x+x:t+x:t^2

Я подумав, що друга частина: "2. Моделі, детерміновані залежними від часу коваріати для перевірки припущення щодо PH", була б частиною, що стосується мого питання. Я сподівався зробити щось із формули, яку ви описуєте, але коли я спробував це, я або отримав помилку, або окрему змінну часу ... Я отримав низьке значення р за часом, хоча :-D
Макс Гордон

@ max-gordon, чи змінна у вашій відповіді кількість чи час, що минув, поки не настане рівномірність? Тому що більшість методів, які ви цитуєте, призначені саме для даних про події.
f1r3br4nd

@ f1r3br4nd: Це кількість (вік в моєму дослідженні), де небезпека непропорційна, тобто вона змінюється з часом у моїй моделі часу до події. Врешті-решт я вирішив розділитись на два різні часові рамки, оскільки мене не вразило 3-D графік - це ніколи не пройшло рецензентів ...
Макс Гордон

Існує різниця між залежними від часу / різними прогнозами та часовою взаємодією. Більшість змінних залежать від часу (секс - виняток). Якщо у вас є одне спостереження на людину, у вас буде мало шансів зробити або залежно від часу аналіз. Метод Андерсона-Гілла найчастіше використовується для аналізу часу на виживання. Перевага методів, що залежать від часу, полягає в тому, що значення під час подальшого спостереження можуть бути більше прогнозуванням досвіду виживання, ніж базові значення. Друга ситуація, провідники, що взаємодіють у часі, - це просто тести припущення щодо PH.
Адам Робінссон

Відповіді:


8

@mpiktas наблизився, запропонувавши можливу модель, однак термін, який потрібно використовувати для квадратичної форми в часі = t буде I(t^2)). Це так, тому що в R інтерпретація формули "^" створює взаємодії і не виконує експоненціації, тому взаємодія "t" з "t" є просто "t". (Чи не слід це перенести на SO із тегом [r]?)

Альтернативи цьому процесу, який мені здається дещо сумнівним для цілей висновку, і той, який, ймовірно, відповідає вашому інтересу до використання підтримуючих функцій у пакетах Р. / Хміска Гаррелла, дивіться у "Стратегії моделювання регресії" Гаррелла. Він згадує (але лише мимохіть, хоча він цитує деякі власні документи), будуючи сплайни, що підходять до часової шкали для моделювання небезпек у формі ванни. У його главі про параметричні моделі виживання описуються різноманітні побудови графіків для перевірки пропорційних припущень про небезпеку та для вивчення лінійності оцінених наслідків небезпеки для журналу в масштабі часу.

Редагувати: додатковою опцією є використання coxph параметра 'stt', описаного як "необов'язковий список функцій перетворення часу".


Я погоджуюся, що це, мабуть, має бути переміщено до тегу SO [r].
Зак

+1 для вашої відповіді, я не знав, що це буде так важко відповісти. Це здається загальною проблемою, можливо, це питання скоріше питання кодування, ніж, і ви можете мати рацію про те, що ТАК є кращим вибором. Я спробував вашу формулу, здається, що vf + I (vf log (time)) чудово підходить, я спробував просто vf time і vf * time ^ 2, але журнал дав за проїзд найменше p-значення. Я спробував запустити його за допомогою функції cph (), щоб отримати AIC, але це дало помилку :( Чи маєте ви уявлення про те, як зробити сюжет на оцінці?
Макс Гордон,

Я подумав, що check <- cox.zph(fit1); print(check); plot(check, resid=F)як у вашій програмі давали інформативні сюжети часу "ефект". Ви мали на увазі cph (), що йде з пакету rms або coxph від виживання?
DWin

Так, залишки Шенфельда дають гарне уявлення про зміну часу, але я думаю, що людям, можливо, важко це зрозуміти. Сюжет дає, як я розумію, залишкові зміни, не пояснені моєю моделлю. Я хотів би хоч сюжет, де я маю повний ефект змінної на вісь y та час на осі x, я вважаю, що це було б простіше інтерпретувати, оскільки вам не потрібно дивитися і на таблицю, і на графік щоб отримати небезпеку в певний момент часу ... Так, я мав на увазі cph (), а не coxph (), оскільки це не працює з AIC ()
Макс Гордон,

Я також трохи розгублений, чому я знайшов усі складні методи, описані в моєму запитанні, в той час як цей я (змінний * час) здається дуже прямим вперед та інтуїтивно зрозумілим - як я нестатист, я думаю - що я пропустив ?
Макс Гордон

5

Я змінив відповідь на це, оскільки ні відповіді @ DWin, ні @ Zach повністю не відповідають, як моделювати коефіцієнти, що змінюються часом. Нещодавно я написав пост про це. Ось суть цього.

год(т)

год(т)=f(т)S(т)

f(т)S(т)0 .

тiме0S(т)

Дозволяючи суб'єктам, що входять в інші моменти часу, ми повинні змінити значення Survз Surv(time, status)на Surv(start_time, end_time, status). Незважаючи на те, що end_timeтест сильно корелює з результатом, start_timeвін зараз доступний як термін взаємодії (так само, як натякано в оригінальних пропозиціях). У звичайній установці start_time0 є, за винятком кількох предметів, які з’являються пізніше, але якщо ми розділимо кожне спостереження на кілька періодів, у нас раптом є багато початкових разів, які не є нульовими. Різниця полягає лише в тому, що кожне спостереження відбувається кілька разів, коли всі, крім останнього, мають можливість нецензурованого результату.

Час поділу на практиці

Щойно я опублікував на CRAN пакет Greg, який робить цей розкол часу легким. Спочатку ми почнемо з деяких теоретичних спостережень:

library(Greg)
test_data <- data.frame(
  id = 1:4,
  time = c(4, 3.5, 1, 5),
  event = c("censored", "dead", "alive", "dead"),
  age = c(62.2, 55.3, 73.7, 46.3),
  date = as.Date(
    c("2003-01-01", 
      "2010-04-01", 
      "2013-09-20",
      "2002-02-23"))
)

Ми можемо показати це графічно, якщо * є індикатором події:

введіть тут опис зображення

Якщо ми застосуємо timeSplitterнаступне:

library(dplyr)
split_data <- 
  test_data %>% 
  select(id, event, time, age, date) %>% 
  timeSplitter(by = 2, # The time that we want to split by
               event_var = "event",
               time_var = "time",
               event_start_status = "alive",
               time_related_vars = c("age", "date"))

Ми отримуємо наступне:

введіть тут опис зображення

Як ви бачите, кожен об'єкт був розділений на кілька подій, коли останній проміжок часу містить фактичний стан події. Це дозволяє нам зараз будувати моделі, які мають прості :умови взаємодії (не використовуйте, *оскільки це розширюється, time + var + time:varі ми самі не зацікавлені часом). Немає необхідності у використанні I()функції, хоча, якщо ви хочете перевірити нелінійність з часом, я часто створюю окрему змінну часу-взаємодії, до якої я додаю сплайн, а потім відображаю за допомогою rms::contrast. У будь-якому випадку, ваш регресний дзвінок зараз повинен виглядати так:

coxp(Surv(start_time, end_time, event) ~ var1 + var2 + var2:time, 
     data = time_split_data)

З допомогою пакета виживання в ttфункцію

Існує також спосіб моделювання залежних від часу коефіцієнтів безпосередньо в пакеті виживання за допомогою ttфункції. Професор Терно подає ретельне ознайомлення з темою у віньєтці . На жаль, у великих наборах даних це важко зробити через обмеження пам'яті. Здається, що ttфункція розбиває час на дуже тонкі фрагменти, утворюючи в процесі величезну матрицю.


2

Ви можете скористатися функцією apply.rolling в PerformanceAnalytics для запуску лінійної регресії через прокатне вікно, що дозволить вашим коефіцієнтам змінюватися в часі.

Наприклад:

library(PerformanceAnalytics)
library(quantmod)
getSymbols(c('AAPL','SPY'), from='01-01-1900')
chart.RollingRegression(Cl(AAPL),Cl(SPY), width=252, attribute='Beta')
#Note: Alpha=y-intercept, Beta=regression coeffient

Це працює і з іншими функціями.


Дякую за вашу відповідь, я думаю, що рухливий час повинен працювати так само добре, як і мої підходи. Я не можу змусити ваш приклад запуститись, чи можете ви, будь ласка, навести приклад на основі мого прикладу sTRACE, щоб я точно знав, як його реалізувати?
Макс Гордон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.