From 8629a52530d2621251b53e0592780a7033514401 Mon Sep 17 00:00:00 2001 From: Louis Chih-Ming Lee Date: Tue, 19 May 2026 17:25:57 +0200 Subject: [PATCH] update --- publish.sh | 2 +- report.Rmd | 32 +++- slides.qmd => slides.Rmd | 159 +++++++++++++++++--- slides.html | 315 +++++++++++++++++++++++++++++---------- 4 files changed, 402 insertions(+), 106 deletions(-) rename slides.qmd => slides.Rmd (82%) diff --git a/publish.sh b/publish.sh index f319fd5..04c97b0 100644 --- a/publish.sh +++ b/publish.sh @@ -19,6 +19,6 @@ git add -A git commit -m "Deploy static site" # Push this folder as the gh-pages branch of chmee/kidney -git push -f git@github.com:chmee/kidney.git main:gh-pages +git push -f git@github.com:chmlee/kidney.git master:gh-pages cd - diff --git a/report.Rmd b/report.Rmd index 89e97dc..f5f6edd 100644 --- a/report.Rmd +++ b/report.Rmd @@ -14,6 +14,7 @@ library(survival) library(emmeans) library(foreign) library(gtsummary) +library(ggsurvfit) ``` ```{r} @@ -114,6 +115,29 @@ table.split <- dat.table1 |> table.split ``` +```{r} +table.split <- dat.table1 |> + select(sex, age.rec, age.donor, hla.match, cold.isc, tx.type) |> + tbl_summary( + by = tx.type, + statistic = list( + all_continuous() ~ "{median} ({p25}, {p75})" + ), + label = list( + hla.match ~ "HLA matches, n(%)", + age.donor ~ "Donor age, median (IQR)", + age.rec ~ "Recipient age, median (IQR)", + cold.isc ~ "Cold ischemic time (hours), median (IQR), ", + sex ~ "Sex, n(%)" + ), + missing = "ifany" + ) |> + add_overall() |> + modify_footnote(all_stat_cols() ~ NA) + +table.split +``` + Calculate median follow-up (reverse Kaplan-Meier method), with 95% CI ```{r} @@ -367,9 +391,6 @@ recode.dat <- function(dat, time.intervals) { df } - - - ``` ```{r} @@ -547,13 +568,16 @@ dat.age.rec$age.group <- sapply(dat.age.rec$age.rec, class.age) |> cox.age.rec <- coxph(Surv(follow.up, death) ~ age.group, data = dat.age.rec) -cox.age.rec |> summary() ``` ```{r} emmeans(cox.age.rec, pairwise ~ age.group, type = "response") ``` +```{r} +cox.age.rec |> ggsurvfit() +``` + # Exercise 7 diff --git a/slides.qmd b/slides.Rmd similarity index 82% rename from slides.qmd rename to slides.Rmd index 81b33bb..871e462 100644 --- a/slides.qmd +++ b/slides.Rmd @@ -284,6 +284,57 @@ dat |> ## Explain Dataset (M) +::: {.callout-note} +# Things to highlight in figures + +- sex and recipient age are similar across `tx.type` + +- Living donors have less `hla.match` then cadaveric donors + +- There is age difference between different `tx.type` +::: + + +### `sex` ~ `tx.tpye` + +::: {.callout-note} +`sex` are similar across `tx.type` +::: + +```{r, fig.width=7, fig.height=5} +dat |> + count(tx.type, sex) |> + group_by(tx.type) |> + mutate( + total = sum(n), + percent = n / total + ) |> + ungroup() |> + ggplot() + + geom_col(aes(x = tx.type, y = percent, fill = sex), position = "dodge") + + labs( + title = "Percentage of Sex in Transplant Type", + y = "Percentage", + x = "Transplant Type", + fill = NULL + + ) + + scale_x_discrete( + labels = c("Cadaveric" = "Deceased"), + ) + + theme_minimal() + + theme( + legend.position = "bottom", + plot.title = element_text(size = 17, face = "bold"), + axis.title = element_text(size = 15), + axis.text = element_text(size = 10), + legend.text = element_text(size = 12), + plot.margin = margin(20, 30, 20, 30) + ) + + +``` + ## Table 1 (L) @@ -308,6 +359,15 @@ ggplot(dat, aes(x = hla.match, fill = tx.type)) + theme_minimal() ``` +::: {.callout-warning} +TODO: change to percentage within each `tx.type` +::: + +::: {.callout-note} +Living donors have less `hla.match` then cadaveric donors +::: + + ### Donor age `age.donor` ```{r} @@ -323,9 +383,7 @@ ggplot(dat, aes(x = age.donor)) + theme_minimal() ``` -```{r} -#| fig-width: 8 -#| fig-height: 12 +```{r, fig.width = 8, fig.height = 12} ggplot(dat, aes(x = age.donor)) + geom_bar() + labs(x = "Donor Age", y = "Count") + @@ -333,6 +391,14 @@ ggplot(dat, aes(x = age.donor)) + facet_grid(hla.match ~ .) ``` +```{r, fig.width= 8, fig.height= 12} +ggplot(dat, aes(x = age.donor, color = tx.type)) + + geom_density() + + labs(x = "Donor Age", y = "Density") + + theme_minimal() + + facet_grid(hla.match ~ .) +``` + ```{r} ggplot(dat, aes(x = age.donor, color = hla.match)) + geom_density() + @@ -340,6 +406,16 @@ ggplot(dat, aes(x = age.donor, color = hla.match)) + theme_minimal() ``` +```{r} +ggplot(dat, aes(x = as.factor(tx.type), y = age.donor)) + + geom_boxplot() + + theme_minimal() +``` + +::: {.callout-note} +There is age difference between different `tx.type` +::: + ### Recipient Age `age.rec` @@ -407,8 +483,19 @@ ggplot(dat, aes(x = cold.isc, color = tx.type, group = tx.type)) + theme_minimal() ``` +```{r} +ggplot(dat, aes(x = cold.isc)) + + geom_density() + + theme_minimal() + + facet_grid(tx.type ~ .) +``` + ### Transplant Type `tx.type` +```{r} +dat$tx.type |> table(useNA = "always") +``` + ```{r} #| echo: true dat$tx.type |> table() @@ -455,10 +542,13 @@ ggplot(dat, aes(x = year, y = age.donor)) + geom_boxplot() ``` -## Overall Kaplan-Meier +## Kaplan-Meier + +### Overall (L) ```{r} km_all <- survfit(Surv(follow.up, death) ~ 1, data = dat) +summary(km_all, times = c(4, 8, 12)) ``` ```{r} @@ -473,7 +563,38 @@ km_all |> theme_minimal() ``` -## Hazard Functions +### `tx.type` (M) + +```{r, fig.width=7, fig.height=5} +km.tx <- survfit(Surv(follow.up, death) ~ tx.type, data = dat) + +km.tx |> + ggsurvfit(type = "survival") + + add_confidence_interval() + + scale_x_continuous( + breaks = seq(0, 20, by = 4) + ) + + scale_y_continuous( + limits = c(0, 1), + breaks = seq(0, 1, by = 0.2), + labels = scales::label_number(accuracy = 0.1) + ) + + labs( + x = "Years of Follow-up", + y = "Overall Survival Probability" + ) + + theme_minimal() + + theme( + legend.position = "bottom", + plot.title = element_text(size = 17, face = "bold"), + axis.title = element_text(size = 15), + axis.text = element_text(size = 10), + legend.text = element_text(size = 12), + plot.margin = margin(20, 30, 20, 30) + ) +``` + +## Cox Model ```{r} get.life.table <- function(dat, time.intervals) { @@ -548,13 +669,13 @@ recode.dat <- function(dat, time.intervals) { ### `death` Distribution (?) ```{r} -dat |> - mutate( - accum.death = cumsum(death), - accum.censored = if_else(death == 1, 0, 1) |> cumsum() - ) |> - ggplot() + - geom_step(aes(x = follow.up, y = accum.death)) +# dat |> +# mutate( +# accum.death = cumsum(death), +# accum.censored = if_else(death == 1, 0, 1) |> cumsum() +# ) |> +# ggplot() + +# geom_pont(aes(x = follow.up, y = accum.death, color = death)) ``` ```{r} @@ -569,7 +690,11 @@ plot.death ``` -### Overall (?) +### Overall (L) + +::: {.callout-note} +skip overall, jump directly to `tx.type` +::: ```{r} time.intervals <- c(1/3, 1/3, 1/3, 1, 1, 1, 1) @@ -579,13 +704,6 @@ get.life.table(dat, time.intervals) ### `tx.type` (M) -```{r} - -``` - - -## Cox Model - ### `age` (continuous) (L) ### `age` (categorical) (M) @@ -607,3 +725,4 @@ anova(m1, m2, test = "LRT") ## Assumption Testing # Conclusion (M + L) + diff --git a/slides.html b/slides.html index 80b495b..260d904 100644 --- a/slides.html +++ b/slides.html @@ -2214,6 +2214,48 @@ window.Quarto = {

2 Method & Result

2.1 Explain Dataset (M)

+
+
+
+ +
+
+Things to highlight in figures +
+
+
+
    +
  • sex and recipient age are similar across tx.type

  • +
  • Living donors have less hla.match then cadaveric donors

  • +
  • There is age difference between different tx.type

  • +
+
+
+
+

2.1.1 sex ~ tx.tpye

+
+
+
+ +
+
+Note +
+
+
+

sex are similar across tx.type

+
+
+
+
+
+
+

+
+
+
+
+

2.2 Table 1 (L)

@@ -2230,7 +2272,7 @@ window.Quarto = {
-

+

@@ -2239,11 +2281,37 @@ window.Quarto = {
-

+

+
+
+
+ +
+
+Warning +
+
+
+

TODO: change to percentage within each tx.type

+
+
+
+
+
+ +
+
+Note +
+
+
+

Living donors have less hla.match then cadaveric donors

+
+

2.2.2 Donor age age.donor

@@ -2265,7 +2333,7 @@ window.Quarto = {
-

+

@@ -2278,7 +2346,7 @@ window.Quarto = {
-

+

@@ -2291,28 +2359,15 @@ window.Quarto = {
-

+

-
-
-

2.2.3 Recipient Age age.rec

-
-
mean(dat$age.rec, na.rm = TRUE)
-
-
[1] 11.64653
-
-
median(dat$age.rec, na.rm = TRUE)
-
-
[1] 13
-
-
-
Warning: Removed 9 rows containing non-finite outside the scale range
-(`stat_count()`).
+
Warning: Removed 113 rows containing non-finite outside the scale range
+(`stat_density()`).
@@ -2335,23 +2390,36 @@ window.Quarto = {
+
+
+
+ +
+
+Note +
+
+
+

There is age difference between different tx.type

+
+
+
+
+

2.2.3 Recipient Age age.rec

-
-
Warning: Removed 9 rows containing non-finite outside the scale range
-(`stat_count()`).
-
-
-
-
-

-
+
mean(dat$age.rec, na.rm = TRUE)
+
+
[1] 11.64653
+
median(dat$age.rec, na.rm = TRUE)
+
+
[1] 13
Warning: Removed 9 rows containing non-finite outside the scale range
-(`stat_density()`).
+(`stat_count()`).
@@ -2363,7 +2431,7 @@ window.Quarto = {
-
Warning: Removed 2250 rows containing non-finite outside the scale range
+
Warning: Removed 113 rows containing non-finite outside the scale range
 (`stat_boxplot()`).
@@ -2374,22 +2442,22 @@ window.Quarto = {
-
-
-

2.2.4 Cold Ischemia Time cold.isc

-
mean(dat$cold.isc, na.rm = TRUE)
-
-
[1] 10.85967
+
+
Warning: Removed 9 rows containing non-finite outside the scale range
+(`stat_count()`).
+
+
+
+
+

+
-
median(dat$cold.isc, na.rm = TRUE)
-
-
[1] 7
-
Warning: Removed 2250 rows containing non-finite outside the scale range
+
Warning: Removed 9 rows containing non-finite outside the scale range
 (`stat_density()`).
@@ -2403,7 +2471,7 @@ window.Quarto = {
Warning: Removed 2250 rows containing non-finite outside the scale range
-(`stat_density()`).
+(`stat_boxplot()`).
@@ -2414,10 +2482,69 @@ window.Quarto = {
+
+

2.2.4 Cold Ischemia Time cold.isc

+
+
mean(dat$cold.isc, na.rm = TRUE)
+
+
[1] 10.85967
+
+
median(dat$cold.isc, na.rm = TRUE)
+
+
[1] 7
+
+
+
+
+
Warning: Removed 2250 rows containing non-finite outside the scale range
+(`stat_density()`).
+
+
+
+
+

+
+
+
+
+
+
+
Warning: Removed 2250 rows containing non-finite outside the scale range
+(`stat_density()`).
+
+
+
+
+

+
+
+
+
+
+
+
Warning: Removed 2250 rows containing non-finite outside the scale range
+(`stat_density()`).
+
+
+
+
+

+
+
+
+
+

2.2.5 Transplant Type tx.type

-
dat$tx.type |> table()
+
+

+Cadaveric    Living      <NA> 
+     5148      4627         0 
+
+
+
+
dat$tx.type |> table()

 Cadaveric    Living 
@@ -2428,7 +2555,7 @@ Cadaveric    Living
 
-

+

@@ -2447,7 +2574,7 @@ Cadaveric Living
-

+

@@ -2456,7 +2583,7 @@ Cadaveric Living
-

+

@@ -2465,7 +2592,7 @@ Cadaveric Living
-

+

@@ -2478,7 +2605,7 @@ Cadaveric Living
-

+

@@ -2491,50 +2618,79 @@ Cadaveric Living
-

+

-
-

2.3 Overall Kaplan-Meier

+
+

2.3 Kaplan-Meier

+
+

2.3.1 Overall (L)

+
+
+
Call: survfit(formula = Surv(follow.up, death) ~ 1, data = dat)
+
+ time n.risk n.event survival std.err lower 95% CI upper 95% CI
+    4   4150     359    0.953 0.00252        0.948        0.958
+    8   1197      86    0.919 0.00449        0.910        0.928
+   12     48      20    0.888 0.00867        0.871        0.905
+
+
-

+

-
-

2.4 Hazard Functions

+
+

2.3.2 tx.type (M)

+
+
+
+
+

+
+
+
+
+
+
+
+

2.4 Cox Model

2.4.1 death Distribution (?)

-

-
-
-
-
-
-
-
-
-

+

-
-

2.4.2 Overall (?)

+
+

2.4.2 Overall (L)

+
+
+
+ +
+
+Note +
+
+
+

skip overall, jump directly to tx.type

+
+
# A tibble: 7 × 5
@@ -2550,20 +2706,17 @@ Cadaveric    Living
 
-
-

2.4.3 tx.type (M)

+
+

2.4.3 tx.type (M)

+
+

2.4.4 age (continuous) (L)

-
-

2.5 Cox Model

-
-

2.5.1 age (continuous) (L)

+
+

2.4.5 age (categorical) (M)

-
-

2.5.2 age (categorical) (M)

-
-
-

2.5.3 Full model (L)

+
+

2.4.6 Full model (L)

Call:
@@ -2654,12 +2807,12 @@ Score (logrank) test = 69.92  on 13 df,   p=8e-10
-
-

2.5.4 Discussion: include year or not?

+
+

2.4.7 Discussion: include year or not?

-
-

2.6 Assumption Testing

+
+

2.5 Assumption Testing