Email: theodoraputrina@gmail.com
RPubs: https://rpubs.com/Theodora
Pada bagian terakhir Bagian 2 kita telah membahas tentang pengenalan konsep dan metode analisis kelangsungan hidup. Di sini, kami fokus pada Competing Risk Analysis (CRA) dengan memilih model dan menilai kecukupan dan kecocokannya. Paket utama untuk digunakan dalam analisis risiko bersaing adalah cmprsk.
Ketika subjek memiliki beberapa kemungkinan kejadian dalam pengaturan waktu ke acara
Contoh:
Semua atau sebagian dari ini (di antara yang lain) mungkin merupakan peristiwa yang mungkin terjadi dalam pembelajaran tertentu.
Ketergantungan yang tidak teramati di antara waktu peristiwa adalah masalah mendasar yang mengarah pada kebutuhan akan pertimbangan khusus. Sebagai contoh, dapat dibayangkan bahwa pasien yang kambuh lebih mungkin meninggal, dan oleh karena itu waktu untuk kambuh dan waktu kematian bukanlah kejadian yang independen.
Dua pendekatan analisis dengan adanya beberapa hasil potensial:
Masing-masing pendekatan ini hanya dapat menerangi satu aspek penting dari data sementara mungkin mengaburkan yang lain, dan pendekatan yang dipilih harus bergantung pada pertanyaan yang menarik.
Saat kami mengerjakan Analisis Risiko Bersaing, berikut beberapa catatan dan referensi tambahan yang harus kami pertimbangkan:
Beberapa referensi yang bisa kita dekati untuk mempelajari lebih lanjut: * Dignam JJ, Zhang Q, Kocherginsky M. The use and interpretation of competing risks regression models. Clin Cancer Res. 2012;18(8):2301-8. * Kim HT. Cumulative incidence in competing risks data and competing risks regression analysis. Clin Cancer Res. 2007 Jan 15;13(2 Pt 1):559-65. * Satagopan JM, Ben-Porat L, Berwick M, Robson M, Kutler D, Auerbach AD. A note on competing risks in survival data analysis. Br J Cancer. 2004;91(7):1229-35. * Austin, P., & Fine, J. (2017). Practical recommendations for reporting Fine‐Gray model analyses for competing risk data. Statistics in Medicine, 36(27), 4391-4400.
Kita menggunakan data Melanoma dari paket MASS untuk menggambarkan konsep ini. Ini berisi variabel:
waktu kelangsungan hidup waktu dalam beberapa hari, mungkin disensor.status 1 meninggal karena melanoma, 2 hidup, 3 meninggal karena sebab lain.jenis kelamin 1 = laki-laki, 0 = perempuan.usia dalam tahun.tahun operasi.ketebalan ketebalan tumor dalam mm.ulkus 1 = kehadiran, 0 = tidak ada.Perkirakan insiden kumulatif dalam konteks risiko bersaing menggunakan fungsi cuminc.
Catatan: dalam data Melanoma, pasien yang disensor diberi kode 2 untuk status, jadi kita tidak dapat menggunakan opsi cencode default 0
## Estimates and Variances:
## $est
## 1000 2000 3000 4000 5000
## 1 1 0.12745714 0.23013963 0.30962017 0.3387175 0.3387175
## 1 3 0.03426709 0.05045644 0.05811143 0.1059471 0.1059471
##
## $var
## 1000 2000 3000 4000 5000
## 1 1 0.0005481186 0.0009001172 0.0013789328 0.001690760 0.001690760
## 1 3 0.0001628354 0.0002451319 0.0002998642 0.001040155 0.001040155
Hasilkan plot R dasar dengan semua default.
Dalam legenda:
Kita juga dapat memplot insiden kumulatif menggunakan fungsi ggscompetingrisks dari paket survminer.
Dalam hal ini kita mendapatkan panel yang diberi label sesuai dengan grup, dan legenda berlabel peristiwa, yang menunjukkan jenis peristiwa untuk setiap baris.
Catatan
multiple panel = FALSE untuk membuat semua grup diplot pada satu panelTes In Cuminc Gray digunakan untuk tes antar-kelompok.
Sebagai contoh, bandingkan hasil Melanoma menurut ulcer, ada atau tidaknya ulserasi. Hasil tes dapat ditemukan di Tes.
ci_ulcer <-
cuminc(
ftime = Melanoma$time,
fstatus = Melanoma$status,
group = Melanoma$ulcer,
cencode = 2
)
ci_ulcer[["Tests"]]## stat pv df
## 1 26.120719 3.207240e-07 1
## 3 0.158662 6.903913e-01 1
Kita juga dapat memvisualisasikan atau memplot insiden kumulatif menurut kelompok dengan menggunakan paket ‘ggcompetingrisks’:
ggcompetingrisks(
fit = ci_ulcer,
multiple_panels = FALSE,
xlab = "Days",
ylab = "Cumulative incidence of event",
title = "Death by ulceration",
ylim = c(0, 1)
)Catatan Saya pribadi menemukan fungsi ggcompetingrisks kurang dalam penyesuaian, terutama dibandingkan dengan ggsurvplot. Saya biasanya melakukan plotting saya sendiri, dengan terlebih dahulu membuat dataset yang rapi dari hasil cuminc fit, dan kemudian memplot hasilnya. Lihat kode sumber untuk presentasi ini untuk rincian kode yang mendasari.
library(tidyverse)
ciplotdat <-
ci_ulcer %>%
list_modify("Tests" = NULL) %>%
map_df(`[`, c("time", "est"), .id = "id") %>%
mutate(id = recode(
id,
"0 1" = "Not ulcerated:Death melanoma",
"0 3" = "Not ulcerated:Death other causes",
"1 1" = "Ulcerated:Death melanoma",
"1 3" = "Ulcerated:Death other causes")
) %>%
separate(id, c("Ulceration", "Event"), ":")
ggplot(ciplotdat, aes(x = time, y = est, color = Ulceration)) +
geom_step(lwd = 1.2, aes(linetype = Event)) +
ylim(c(0, 1)) +
theme_classic() +
theme(plot.title = element_text(size = 14),
legend.title = element_blank(),
legend.position = "bottom") +
labs(x = "Days",
y = "Cumulative incidence",
title = "Death by ulceration status") +
annotate("text", x = 0, y = 1, hjust = 0,
label = paste0(
"Death melanoma p = ",
ifelse(ci_ulcer$Tests[1, 2] < .001,
"<.001",
round(ci_ulcer$Tests[1, 2], 3)))) +
annotate("text", x = 0, y = 0.92, hjust = 0,
label = paste0(
"Death other causes p = ",
ifelse(ci_ulcer$Tests[2, 2] < .001,
"<.001",
round(ci_ulcer$Tests[2, 2], 3)))) Seringkali hanya satu dari jenis acara yang menarik, meskipun kami masih ingin memperhitungkan acara yang bersaing. Dalam hal ini acara yang menarik dapat direncanakan sendiri. Sekali lagi, saya melakukan ini secara manual dengan terlebih dahulu membuat set data yang rapi dari hasil cuminc fit, dan kemudian memplot hasilnya. Lihat kode sumber untuk presentasi ini untuk rincian kode yang mendasari.
ciplotdat1 <-
ci_ulcer %>%
list_modify("Tests" = NULL) %>%
map_df(`[`, c("time", "est"), .id = "id") %>%
filter(id %in% c("0 1", "1 1")) %>%
mutate(Ulceration = recode(
id,
"0 1" = "Not ulcerated",
"1 1" = "Ulcerated")
)
ggplot(ciplotdat1, aes(x = time, y = est, color = Ulceration)) +
geom_step(lwd = 1.2) +
ylim(c(0, 1)) +
theme_classic() +
theme(plot.title = element_text(size = 14),
legend.title = element_blank(),
legend.position = "bottom") +
labs(x = "Days",
y = "Cumulative incidence",
title = "Melanoma death by ulceration status") +
annotate("text", x = 0, y = 1, hjust = 0,
label = paste0(
"p-value = ",
ifelse(ci_ulcer$Tests[1, 2] < .001,
"<.001",
round(ci_ulcer$Tests[1, 2], 3))))Anda mungkin ingin menambahkan jumlah tabel risiko ke plot insiden kumulatif, dan tidak ada cara mudah untuk melakukan ini yang saya ketahui. Lihat kode sumber untuk presentasi ini untuk satu contoh (dengan permintaan populer, kode sumber sekarang disertakan langsung di bawah untuk satu contoh spesifik)
ggcompetingrisks, atau ggplotmel_plot <-
ggplot(ciplotdat1, aes(x = time, y = est, color = Ulceration)) +
geom_step(lwd = 1.2) +
ylim(c(0, 1)) +
coord_cartesian(xlim = c(0, 5000)) +
scale_x_continuous(breaks = seq(0, 5000, 1000)) +
theme_classic() +
theme(plot.title = element_text(size = 14),
legend.title = element_blank(),
legend.position = "bottom") +
labs(x = "Days",
y = "Cumulative incidence",
title = "Melanoma death by ulceration status") +
annotate("text", x = 0, y = 1, hjust = 0,
label = paste0(
"p-value = ",
ifelse(ci_ulcer$Tests[1, 2] < .001,
"<.001",
round(ci_ulcer$Tests[1, 2], 3))))Dapatkan tabel nomor berisiko dari ggsurvplot menggunakan survfit di mana semua peristiwa dihitung sebagai titik akhir komposit tunggal
mel_fit <- survfit(
Surv(time, ifelse(status != 2, 1, 0)) ~ ulcer,
data = Melanoma
)
num <- ggsurvplot(
fit = mel_fit,
risk.table = TRUE,
risk.table.y.text = FALSE,
ylab = "Days",
risk.table.fontsize = 3.2,
tables.theme = theme_survminer(font.main = 10),
title = "Test"
)Kemudian gabungkan plot dan risktable. Saya menggunakan fungsi plot_grid dari paket cowplot untuk ini
table.theme = theme_survminer (font.main = 10)!cowplot::plot_grid(
mel_plot,
num$table + theme_cleantable(),
nrow = 2,
rel_heights = c(4, 1),
align = "v",
axis = "b"
)Dua pendekatan:
Katakanlah kita tertarik untuk melihat pengaruh usia dan jenis kelamin pada kematian akibat melanoma, dengan kematian akibat penyebab lain sebagai acara yang bersaing.
Catatan:
kode gagal, secara default hasil dikembalikan untuk kode gagal = 1shr_fit <-
crr(
ftime = Melanoma$time,
fstatus = Melanoma$status,
cov1 = Melanoma[, c("sex", "age")],
cencode = 2
)
shr_fit## convergence: TRUE
## coefficients:
## sex age
## 0.58840 0.01259
## standard errors:
## [1] 0.271800 0.009301
## two-sided p-values:
## sex age
## 0.03 0.18
Dalam contoh sebelumnya, baik sex dan age diberi kode sebagai variabel numerik. Fungsi crr tidak dapat menangani variabel karakter secara alami, dan Anda akan mendapatkan error, jadi jika variabel karakter ada, kita harus membuat variabel dummy menggunakan model.matrix
# Create an example character variable
chardat <-
Melanoma %>%
mutate(
sex_char = ifelse(sex == 0, "Male", "Female")
)
# Create dummy variables with model.matrix
# The [, -1] removes the intercept
covs1 <- model.matrix(~ sex_char + age, data = chardat)[, -1]
# Now we can pass that to the cov1 argument, and it will work
crr(
ftime = chardat$time,
fstatus = chardat$status,
cov1 = covs1,
cencode = 2
)## convergence: TRUE
## coefficients:
## sex_charMale age
## -0.58840 0.01259
## standard errors:
## [1] 0.271800 0.009301
## two-sided p-values:
## sex_charMale age
## 0.03 0.18
Keluaran dari crr saat ini tidak didukung oleh broom::tidy() atau gtsummary::tbl_regress(). Sebagai alternatif, coba mvcrrres (tidak fleksibel, tapi lebih baik daripada tidak sama sekali?) Dari paket ezfun saya
| HR (95% CI) | p-value | |
|---|---|---|
| sex | 1.8 (1.06, 3.07) | 0.03 |
| age | 1.01 (0.99, 1.03) | 0.18 |
Menyensor semua subjek yang tidak memiliki kejadian yang diinginkan, dalam hal ini kematian akibat melanoma, dan menggunakan coxph seperti sebelumnya. Jadi, pasien yang meninggal karena penyebab lain sekarang disensor untuk pendekatan bahaya spesifik penyebab terhadap risiko yang bersaing.
Hasil dapat diformat dengan broom::tidy() atau gtsummary:: tbl_regress()
chr_fit <-
coxph(
Surv(time, ifelse(status == 1, 1, 0)) ~ sex + age,
data = Melanoma
)
broom::tidy(chr_fit, exp = TRUE) %>%
kable()| term | estimate | std.error | statistic | p.value |
|---|---|---|---|---|
| sex | 1.818949 | 0.2676386 | 2.235323 | 0.0253961 |
| age | 1.016679 | 0.0086628 | 1.909514 | 0.0561958 |
| Characteristic | HR1 | 95% CI1 | p-value |
|---|---|---|---|
| sex | 1.82 | 1.08, 3.07 | 0.025 |
| age | 1.02 | 1.00, 1.03 | 0.056 |
|
1
HR = Hazard Ratio, CI = Confidence Interval
|
|||