git init
This commit is contained in:
commit
7b94e4bf64
5 changed files with 10913 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
*_cache/
|
||||||
|
*_files/
|
||||||
BIN
Assignment_1.pdf
Normal file
BIN
Assignment_1.pdf
Normal file
Binary file not shown.
244
report.Rmd
Normal file
244
report.Rmd
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
---
|
||||||
|
title: foo
|
||||||
|
execute:
|
||||||
|
cache: true
|
||||||
|
freeze: auto
|
||||||
|
number-sections: true
|
||||||
|
---
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
library(tidyverse)
|
||||||
|
library(survival)
|
||||||
|
# library(gtsummary)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
dat <- read.csv("./unos.txt", sep = "\t")
|
||||||
|
head(dat)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
names(dat) <- c("hla.match", "age.donor", "age.rec", "cold.isc", "death",
|
||||||
|
"year", "sex", "tx.type", "follow.up")
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Exercise
|
||||||
|
|
||||||
|
## Exercise 1
|
||||||
|
|
||||||
|
> Illustrate in a table the characteristics of the population (age, sex, race,
|
||||||
|
donor, . . . ).
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
g <- ggplot(dat)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
g + geom_point(aes(x = follow.up, y = death))
|
||||||
|
g + geom_density(aes(x = follow.up))
|
||||||
|
|
||||||
|
g + geom_density(aes(x = age.donor))
|
||||||
|
g + geom_bar(aes(x = age.rec))
|
||||||
|
|
||||||
|
g + geom_boxplot(aes(x = age.rec, y = age.donor, group = age.donor))
|
||||||
|
|
||||||
|
# dat$age.1 |> table()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exercise 2
|
||||||
|
|
||||||
|
Plot the Kaplan-Meier overall survival curve for pediatric kid-
|
||||||
|
ney transplant recipients for the first 12 years after transplantation.
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
km <- survfit(Surv(follow.up, death) ~ 1, data = dat[dat$follow.up <= 12, ])
|
||||||
|
plot(km)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exercise 3
|
||||||
|
|
||||||
|
We are going to compare mortality rates (hazard functions)
|
||||||
|
between children whose transplanted kidney was provided by a living donor
|
||||||
|
(in general a family member) and those whose source was recently deceased
|
||||||
|
(variable donor type: `txtype`). Use the life table method to calculate the death
|
||||||
|
rates for the first 5 years for each group (take in the first year intervals of 4
|
||||||
|
months and then look at each year) and show the results in a table. Estimate
|
||||||
|
the hazard ratio in each time interval as the ratio between the mortality rates
|
||||||
|
in the two groups. What do you notice?
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
dat.5 <- dat[dat$follow.up <= 5, ]
|
||||||
|
head(dat.5)
|
||||||
|
classify_time_interval = function(fu) {
|
||||||
|
if (fu <= 1/3) {
|
||||||
|
return(1/3)
|
||||||
|
} else if (fu <= 2/3) {
|
||||||
|
return(2/3)
|
||||||
|
} else if (fu <= 1) {
|
||||||
|
return(1)
|
||||||
|
}
|
||||||
|
ceiling(fu)
|
||||||
|
}
|
||||||
|
|
||||||
|
dat.5$fu.interval <- sapply(dat.5$follow.up, classify_time_interval)
|
||||||
|
table(dat.5$fu.interval)
|
||||||
|
head(dat.5)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
dat.5.life <- dat.5 |>
|
||||||
|
group_by(fu.interval) |>
|
||||||
|
summarize(
|
||||||
|
n.censored = sum(death == 0),
|
||||||
|
n.event = sum(death),
|
||||||
|
n.at.risk = nrow(dat),
|
||||||
|
)
|
||||||
|
|
||||||
|
for (i in 2:nrow(dat.5.life)) {
|
||||||
|
j <- i - 1
|
||||||
|
|
||||||
|
n.censored.pre <- dat.5.life$n.censored[j]
|
||||||
|
n.event.pre <- dat.5.life$n.event[j]
|
||||||
|
n.at.risk.pre <- dat.5.life$n.at.risk[j]
|
||||||
|
|
||||||
|
n.at.risk <- n.at.risk.pre - n.event.pre - n.censored.pre
|
||||||
|
|
||||||
|
dat.5.life$n.at.risk[i] <- n.at.risk
|
||||||
|
}
|
||||||
|
|
||||||
|
print(nrow(dat))
|
||||||
|
dat.5.life
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
dat.5.life <- dat.5.life |>
|
||||||
|
mutate(
|
||||||
|
hazard.rate = n.event / n.at.risk
|
||||||
|
)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
get_life_table = function(dat) {
|
||||||
|
dat <- dat |>
|
||||||
|
group_by(fu.interval) |>
|
||||||
|
summarize(
|
||||||
|
n.censored = sum(death == 0),
|
||||||
|
n.event = sum(death),
|
||||||
|
n.at.risk = nrow(dat),
|
||||||
|
)
|
||||||
|
|
||||||
|
for (i in 2:nrow(dat)) {
|
||||||
|
j <- i - 1
|
||||||
|
|
||||||
|
n.censored.pre <- dat$n.censored[j]
|
||||||
|
n.event.pre <- dat$n.event[j]
|
||||||
|
n.at.risk.pre <- dat$n.at.risk[j]
|
||||||
|
|
||||||
|
n.at.risk <- n.at.risk.pre - n.event.pre - n.censored.pre
|
||||||
|
|
||||||
|
dat$n.at.risk[i] <- n.at.risk
|
||||||
|
}
|
||||||
|
|
||||||
|
dat <- dat |>
|
||||||
|
mutate(
|
||||||
|
hazard.rate = n.event / n.at.risk
|
||||||
|
)
|
||||||
|
|
||||||
|
return(dat)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
dat.5.tx0 = dat.5[dat.5$tx.type == 0, ]
|
||||||
|
dat.5.tx1 = dat.5[dat.5$tx.type == 1, ]
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
tx0.life <- get_life_table(dat.5.tx0)
|
||||||
|
tx0.life
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
tx1.life <- get_life_table(dat.5.tx1)
|
||||||
|
tx1.life
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
tx1.life$hazard.rate / tx0.life$hazard.rate
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
hazard.df <- data.frame(
|
||||||
|
fu.interval = tx1.life$fu.interval,
|
||||||
|
hazard.rate.0 = tx0.life$hazard.rate,
|
||||||
|
hazard.rate.1 = tx1.life$hazard.rate,
|
||||||
|
hazard.ratio = tx1.life$hazard.rate / tx0.life$hazard.rate
|
||||||
|
)
|
||||||
|
|
||||||
|
ggplot(hazard.df, aes(x = fu.interval)) +
|
||||||
|
geom_line(aes(y = hazard.rate.0), color = "blue") +
|
||||||
|
geom_line(aes(y = hazard.rate.1), color = "orange")
|
||||||
|
|
||||||
|
ggplot(hazard.df, aes(x = fu.interval)) +
|
||||||
|
geom_line(aes(y = hazard.ratio))
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Exercise 4
|
||||||
|
|
||||||
|
Show a plot with Kaplan-Meier survival curves for the two donor types.
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
km.tx <- survfit(Surv(follow.up, death) ~ tx.type, data = dat[dat$follow.up <= 12, ])
|
||||||
|
|
||||||
|
plot(km.tx, col = c("blue", "orange"))
|
||||||
|
legend(legend = c("cadaveric", "living"), "bottomleft", lwd = 2, col = c("blue", "orange"))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exercise 5
|
||||||
|
|
||||||
|
Fit a univariate Cox model with predictor donor type. Report
|
||||||
|
the hazard ratio and 95% confidence interval and interpret the result obtained.
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
cox <- coxph(Surv(follow.up, death) ~ tx.type, data = dat)
|
||||||
|
summary(cox)
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
1.90539
|
||||||
|
```
|
||||||
|
|
||||||
|
```{r}
|
||||||
|
1.90539 + 1.96 * exp(0.09558)
|
||||||
|
(2.298 - 1.58) / 2 |> exp() / 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Exercise 6 — Research shows that an important determinant of mortality
|
||||||
|
after kidney transplant is the age of the recipient. Fit a Cox model with age
|
||||||
|
as predictor and estimate the hazard ratio and its confidence interval. Consider
|
||||||
|
age first as continuous variable and then divide into categories.
|
||||||
|
|
||||||
|
Exercise 7 — Fit a multivariate Cox model by using other predictors and
|
||||||
|
describe your results.
|
||||||
|
|
||||||
|
Exercise 8 — Estimate the survival function for specific covariate patterns.
|
||||||
|
Based on the previous results choose the best predictors.
|
||||||
|
|
||||||
|
Exercise 9 — Check the proportional hazards assumption. You may use the
|
||||||
|
function cox.zph. Discuss the result and possible implications.
|
||||||
|
Exercise 10 — Plot the Schoenfeld residuals and comment.
|
||||||
|
|
||||||
891
report.html
Normal file
891
report.html
Normal file
|
|
@ -0,0 +1,891 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="generator" content="quarto-1.7.34">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||||
|
|
||||||
|
|
||||||
|
<title>foo</title>
|
||||||
|
<style>
|
||||||
|
code{white-space: pre-wrap;}
|
||||||
|
span.smallcaps{font-variant: small-caps;}
|
||||||
|
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||||||
|
div.column{flex: auto; overflow-x: auto;}
|
||||||
|
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||||
|
ul.task-list{list-style: none;}
|
||||||
|
ul.task-list li input[type="checkbox"] {
|
||||||
|
width: 0.8em;
|
||||||
|
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
/* CSS for syntax highlighting */
|
||||||
|
html { -webkit-text-size-adjust: 100%; }
|
||||||
|
pre > code.sourceCode { white-space: pre; position: relative; }
|
||||||
|
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
||||||
|
pre > code.sourceCode > span:empty { height: 1.2em; }
|
||||||
|
.sourceCode { overflow: visible; }
|
||||||
|
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
||||||
|
div.sourceCode { margin: 1em 0; }
|
||||||
|
pre.sourceCode { margin: 0; }
|
||||||
|
@media screen {
|
||||||
|
div.sourceCode { overflow: auto; }
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
pre > code.sourceCode { white-space: pre-wrap; }
|
||||||
|
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
||||||
|
}
|
||||||
|
pre.numberSource code
|
||||||
|
{ counter-reset: source-line 0; }
|
||||||
|
pre.numberSource code > span
|
||||||
|
{ position: relative; left: -4em; counter-increment: source-line; }
|
||||||
|
pre.numberSource code > span > a:first-child::before
|
||||||
|
{ content: counter(source-line);
|
||||||
|
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
||||||
|
border: none; display: inline-block;
|
||||||
|
-webkit-touch-callout: none; -webkit-user-select: none;
|
||||||
|
-khtml-user-select: none; -moz-user-select: none;
|
||||||
|
-ms-user-select: none; user-select: none;
|
||||||
|
padding: 0 4px; width: 4em;
|
||||||
|
}
|
||||||
|
pre.numberSource { margin-left: 3em; padding-left: 4px; }
|
||||||
|
div.sourceCode
|
||||||
|
{ }
|
||||||
|
@media screen {
|
||||||
|
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="report_files/libs/clipboard/clipboard.min.js"></script>
|
||||||
|
<script src="report_files/libs/quarto-html/quarto.js" type="module"></script>
|
||||||
|
<script src="report_files/libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||||||
|
<script src="report_files/libs/quarto-html/popper.min.js"></script>
|
||||||
|
<script src="report_files/libs/quarto-html/tippy.umd.min.js"></script>
|
||||||
|
<script src="report_files/libs/quarto-html/anchor.min.js"></script>
|
||||||
|
<link href="report_files/libs/quarto-html/tippy.css" rel="stylesheet">
|
||||||
|
<link href="report_files/libs/quarto-html/quarto-syntax-highlighting-c8ad9e5dbd60b7b70b38521ab19b7da4.css" rel="stylesheet" id="quarto-text-highlighting-styles">
|
||||||
|
<script src="report_files/libs/bootstrap/bootstrap.min.js"></script>
|
||||||
|
<link href="report_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="report_files/libs/bootstrap/bootstrap-0e7144b51b1311dce330ab5b48d20e8e.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="fullcontent quarto-light">
|
||||||
|
|
||||||
|
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
|
||||||
|
|
||||||
|
<main class="content" id="quarto-document-content">
|
||||||
|
|
||||||
|
<header id="title-block-header" class="quarto-title-block default">
|
||||||
|
<div class="quarto-title">
|
||||||
|
<h1 class="title">foo</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="quarto-title-meta">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(tidyverse)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stderr">
|
||||||
|
<pre><code>── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
|
||||||
|
✔ dplyr 1.1.4 ✔ readr 2.1.5
|
||||||
|
✔ forcats 1.0.0 ✔ stringr 1.5.1
|
||||||
|
✔ lubridate 1.9.4 ✔ tibble 3.3.0
|
||||||
|
✔ purrr 1.1.0 ✔ tidyr 1.3.1
|
||||||
|
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
|
||||||
|
✖ dplyr::filter() masks stats::filter()
|
||||||
|
✖ dplyr::lag() masks stats::lag()
|
||||||
|
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(survival)</span>
|
||||||
|
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co"># library(gtsummary)</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb4"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>dat <span class="ot"><-</span> <span class="fu">read.csv</span>(<span class="st">"./unos.txt"</span>, <span class="at">sep =</span> <span class="st">"</span><span class="sc">\t</span><span class="st">"</span>)</span>
|
||||||
|
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span>(dat)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code> hlamat age age.1 cold_isc death year sex txtype fu
|
||||||
|
1 2 25 15 6 0 2002 0 1 0
|
||||||
|
2 1 42 10 11 1 1999 0 1 0
|
||||||
|
3 1 9 14 8 0 2002 1 1 0
|
||||||
|
4 0 35 12 26 0 2002 1 1 0
|
||||||
|
5 2 17 12 28 1 1997 1 1 0
|
||||||
|
6 3 44 13 1 0 2002 1 0 0</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb6"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">names</span>(dat) <span class="ot"><-</span> <span class="fu">c</span>(<span class="st">"hla.match"</span>, <span class="st">"age.donor"</span>, <span class="st">"age.rec"</span>, <span class="st">"cold.isc"</span>, <span class="st">"death"</span>,</span>
|
||||||
|
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="st">"year"</span>, <span class="st">"sex"</span>, <span class="st">"tx.type"</span>, <span class="st">"follow.up"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<section id="exercise" class="level1" data-number="1">
|
||||||
|
<h1 data-number="1"><span class="header-section-number">1</span> Exercise</h1>
|
||||||
|
<section id="exercise-1" class="level2" data-number="1.1">
|
||||||
|
<h2 data-number="1.1" class="anchored" data-anchor-id="exercise-1"><span class="header-section-number">1.1</span> Exercise 1</h2>
|
||||||
|
<blockquote class="blockquote">
|
||||||
|
<p>Illustrate in a table the characteristics of the population (age, sex, race, donor, . . . ).</p>
|
||||||
|
</blockquote>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb7"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>g <span class="ot"><-</span> <span class="fu">ggplot</span>(dat)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb8"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>g <span class="sc">+</span> <span class="fu">geom_point</span>(<span class="fu">aes</span>(<span class="at">x =</span> follow.up, <span class="at">y =</span> death))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-5-1.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb9"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>g <span class="sc">+</span> <span class="fu">geom_density</span>(<span class="fu">aes</span>(<span class="at">x =</span> follow.up))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-5-2.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb10"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>g <span class="sc">+</span> <span class="fu">geom_density</span>(<span class="fu">aes</span>(<span class="at">x =</span> age.donor))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stderr">
|
||||||
|
<pre><code>Warning: Removed 113 rows containing non-finite outside the scale range
|
||||||
|
(`stat_density()`).</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-5-3.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb12"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>g <span class="sc">+</span> <span class="fu">geom_bar</span>(<span class="fu">aes</span>(<span class="at">x =</span> age.rec))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stderr">
|
||||||
|
<pre><code>Warning: Removed 9 rows containing non-finite outside the scale range
|
||||||
|
(`stat_count()`).</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-5-4.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>g <span class="sc">+</span> <span class="fu">geom_boxplot</span>(<span class="fu">aes</span>(<span class="at">x =</span> age.rec, <span class="at">y =</span> age.donor, <span class="at">group =</span> age.donor))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stderr">
|
||||||
|
<pre><code>Warning: Removed 113 rows containing missing values or values outside the scale range
|
||||||
|
(`stat_boxplot()`).</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="cell-output cell-output-stderr">
|
||||||
|
<pre><code>Warning: Removed 7 rows containing non-finite outside the scale range
|
||||||
|
(`stat_boxplot()`).</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-5-5.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb17"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="co"># dat$age.1 |> table()</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="exercise-2" class="level2" data-number="1.2">
|
||||||
|
<h2 data-number="1.2" class="anchored" data-anchor-id="exercise-2"><span class="header-section-number">1.2</span> Exercise 2</h2>
|
||||||
|
<p>Plot the Kaplan-Meier overall survival curve for pediatric kid- ney transplant recipients for the first 12 years after transplantation.</p>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb18"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>km <span class="ot"><-</span> <span class="fu">survfit</span>(<span class="fu">Surv</span>(follow.up, death) <span class="sc">~</span> <span class="dv">1</span>, <span class="at">data =</span> dat[dat<span class="sc">$</span>follow.up <span class="sc"><=</span> <span class="dv">12</span>, ])</span>
|
||||||
|
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(km)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-6-1.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="exercise-3" class="level2" data-number="1.3">
|
||||||
|
<h2 data-number="1.3" class="anchored" data-anchor-id="exercise-3"><span class="header-section-number">1.3</span> Exercise 3</h2>
|
||||||
|
<p>We are going to compare mortality rates (hazard functions) between children whose transplanted kidney was provided by a living donor (in general a family member) and those whose source was recently deceased (variable donor type: <code>txtype</code>). Use the life table method to calculate the death rates for the first 5 years for each group (take in the first year intervals of 4 months and then look at each year) and show the results in a table. Estimate the hazard ratio in each time interval as the ratio between the mortality rates in the two groups. What do you notice?</p>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb19"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>dat<span class="fl">.5</span> <span class="ot"><-</span> dat[dat<span class="sc">$</span>follow.up <span class="sc"><=</span> <span class="dv">5</span>, ]</span>
|
||||||
|
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span>(dat<span class="fl">.5</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code> hla.match age.donor age.rec cold.isc death year sex tx.type follow.up
|
||||||
|
1 2 25 15 6 0 2002 0 1 0
|
||||||
|
2 1 42 10 11 1 1999 0 1 0
|
||||||
|
3 1 9 14 8 0 2002 1 1 0
|
||||||
|
4 0 35 12 26 0 2002 1 1 0
|
||||||
|
5 2 17 12 28 1 1997 1 1 0
|
||||||
|
6 3 44 13 1 0 2002 1 0 0</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb21"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>classify_time_interval <span class="ot">=</span> <span class="cf">function</span>(fu) {</span>
|
||||||
|
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> (fu <span class="sc"><=</span> <span class="dv">1</span><span class="sc">/</span><span class="dv">3</span>) {</span>
|
||||||
|
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span>(<span class="dv">1</span><span class="sc">/</span><span class="dv">3</span>)</span>
|
||||||
|
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a> } <span class="cf">else</span> <span class="cf">if</span> (fu <span class="sc"><=</span> <span class="dv">2</span><span class="sc">/</span><span class="dv">3</span>) {</span>
|
||||||
|
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span>(<span class="dv">2</span><span class="sc">/</span><span class="dv">3</span>)</span>
|
||||||
|
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a> } <span class="cf">else</span> <span class="cf">if</span> (fu <span class="sc"><=</span> <span class="dv">1</span>) {</span>
|
||||||
|
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span>(<span class="dv">1</span>)</span>
|
||||||
|
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a> }</span>
|
||||||
|
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">ceiling</span>(fu)</span>
|
||||||
|
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>}</span>
|
||||||
|
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>dat<span class="fl">.5</span><span class="sc">$</span>fu.interval <span class="ot"><-</span> <span class="fu">sapply</span>(dat<span class="fl">.5</span><span class="sc">$</span>follow.up, classify_time_interval)</span>
|
||||||
|
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a><span class="fu">table</span>(dat<span class="fl">.5</span><span class="sc">$</span>fu.interval)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>
|
||||||
|
0.333333333333333 0.666666666666667 1 2
|
||||||
|
982 528 640 1226
|
||||||
|
3 4 5
|
||||||
|
1184 1093 950 </code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb23"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="fu">head</span>(dat<span class="fl">.5</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code> hla.match age.donor age.rec cold.isc death year sex tx.type follow.up
|
||||||
|
1 2 25 15 6 0 2002 0 1 0
|
||||||
|
2 1 42 10 11 1 1999 0 1 0
|
||||||
|
3 1 9 14 8 0 2002 1 1 0
|
||||||
|
4 0 35 12 26 0 2002 1 1 0
|
||||||
|
5 2 17 12 28 1 1997 1 1 0
|
||||||
|
6 3 44 13 1 0 2002 1 0 0
|
||||||
|
fu.interval
|
||||||
|
1 0.3333333
|
||||||
|
2 0.3333333
|
||||||
|
3 0.3333333
|
||||||
|
4 0.3333333
|
||||||
|
5 0.3333333
|
||||||
|
6 0.3333333</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb25"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>dat.<span class="fl">5.</span>life <span class="ot"><-</span> dat<span class="fl">.5</span> <span class="sc">|></span></span>
|
||||||
|
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">group_by</span>(fu.interval) <span class="sc">|></span></span>
|
||||||
|
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">summarize</span>(</span>
|
||||||
|
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a> <span class="at">n.censored =</span> <span class="fu">sum</span>(death <span class="sc">==</span> <span class="dv">0</span>),</span>
|
||||||
|
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a> <span class="at">n.event =</span> <span class="fu">sum</span>(death),</span>
|
||||||
|
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a> <span class="at">n.at.risk =</span> <span class="fu">nrow</span>(dat),</span>
|
||||||
|
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a> )</span>
|
||||||
|
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> (i <span class="cf">in</span> <span class="dv">2</span><span class="sc">:</span><span class="fu">nrow</span>(dat.<span class="fl">5.</span>life)) {</span>
|
||||||
|
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a> j <span class="ot"><-</span> i <span class="sc">-</span> <span class="dv">1</span></span>
|
||||||
|
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a> n.censored.pre <span class="ot"><-</span> dat.<span class="fl">5.</span>life<span class="sc">$</span>n.censored[j]</span>
|
||||||
|
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a> n.event.pre <span class="ot"><-</span> dat.<span class="fl">5.</span>life<span class="sc">$</span>n.event[j]</span>
|
||||||
|
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a> n.at.risk.pre <span class="ot"><-</span> dat.<span class="fl">5.</span>life<span class="sc">$</span>n.at.risk[j]</span>
|
||||||
|
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a> n.at.risk <span class="ot"><-</span> n.at.risk.pre <span class="sc">-</span> n.event.pre <span class="sc">-</span> n.censored.pre</span>
|
||||||
|
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a> dat.<span class="fl">5.</span>life<span class="sc">$</span>n.at.risk[i] <span class="ot"><-</span> n.at.risk</span>
|
||||||
|
<span id="cb25-19"><a href="#cb25-19" aria-hidden="true" tabindex="-1"></a>}</span>
|
||||||
|
<span id="cb25-20"><a href="#cb25-20" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb25-21"><a href="#cb25-21" aria-hidden="true" tabindex="-1"></a><span class="fu">print</span>(<span class="fu">nrow</span>(dat))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>[1] 9775</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb27"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>dat.<span class="fl">5.</span>life</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code># A tibble: 7 × 4
|
||||||
|
fu.interval n.censored n.event n.at.risk
|
||||||
|
<dbl> <int> <int> <int>
|
||||||
|
1 0.333 830 152 9775
|
||||||
|
2 0.667 491 37 8793
|
||||||
|
3 1 613 27 8265
|
||||||
|
4 2 1164 62 7625
|
||||||
|
5 3 1143 41 6399
|
||||||
|
6 4 1053 40 5215
|
||||||
|
7 5 919 31 4122</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb29"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>dat.<span class="fl">5.</span>life <span class="ot"><-</span> dat.<span class="fl">5.</span>life <span class="sc">|></span></span>
|
||||||
|
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">mutate</span>(</span>
|
||||||
|
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a> <span class="at">hazard.rate =</span> n.event <span class="sc">/</span> n.at.risk</span>
|
||||||
|
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a> )</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb30"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>get_life_table <span class="ot">=</span> <span class="cf">function</span>(dat) {</span>
|
||||||
|
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a> dat <span class="ot"><-</span> dat <span class="sc">|></span></span>
|
||||||
|
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a> <span class="fu">group_by</span>(fu.interval) <span class="sc">|></span></span>
|
||||||
|
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">summarize</span>(</span>
|
||||||
|
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a> <span class="at">n.censored =</span> <span class="fu">sum</span>(death <span class="sc">==</span> <span class="dv">0</span>),</span>
|
||||||
|
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a> <span class="at">n.event =</span> <span class="fu">sum</span>(death),</span>
|
||||||
|
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a> <span class="at">n.at.risk =</span> <span class="fu">nrow</span>(dat),</span>
|
||||||
|
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a> )</span>
|
||||||
|
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> (i <span class="cf">in</span> <span class="dv">2</span><span class="sc">:</span><span class="fu">nrow</span>(dat)) {</span>
|
||||||
|
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a> j <span class="ot"><-</span> i <span class="sc">-</span> <span class="dv">1</span></span>
|
||||||
|
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a> n.censored.pre <span class="ot"><-</span> dat<span class="sc">$</span>n.censored[j]</span>
|
||||||
|
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a> n.event.pre <span class="ot"><-</span> dat<span class="sc">$</span>n.event[j]</span>
|
||||||
|
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a> n.at.risk.pre <span class="ot"><-</span> dat<span class="sc">$</span>n.at.risk[j]</span>
|
||||||
|
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a> n.at.risk <span class="ot"><-</span> n.at.risk.pre <span class="sc">-</span> n.event.pre <span class="sc">-</span> n.censored.pre</span>
|
||||||
|
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a> dat<span class="sc">$</span>n.at.risk[i] <span class="ot"><-</span> n.at.risk</span>
|
||||||
|
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a> }</span>
|
||||||
|
<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a> dat <span class="ot"><-</span> dat <span class="sc">|></span></span>
|
||||||
|
<span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a> <span class="fu">mutate</span>(</span>
|
||||||
|
<span id="cb30-24"><a href="#cb30-24" aria-hidden="true" tabindex="-1"></a> <span class="at">hazard.rate =</span> n.event <span class="sc">/</span> n.at.risk</span>
|
||||||
|
<span id="cb30-25"><a href="#cb30-25" aria-hidden="true" tabindex="-1"></a> )</span>
|
||||||
|
<span id="cb30-26"><a href="#cb30-26" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb30-27"><a href="#cb30-27" aria-hidden="true" tabindex="-1"></a> <span class="fu">return</span>(dat)</span>
|
||||||
|
<span id="cb30-28"><a href="#cb30-28" aria-hidden="true" tabindex="-1"></a>}</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb31"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>dat.<span class="fl">5.</span>tx0 <span class="ot">=</span> dat<span class="fl">.5</span>[dat<span class="fl">.5</span><span class="sc">$</span>tx.type <span class="sc">==</span> <span class="dv">0</span>, ]</span>
|
||||||
|
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>dat.<span class="fl">5.</span>tx1 <span class="ot">=</span> dat<span class="fl">.5</span>[dat<span class="fl">.5</span><span class="sc">$</span>tx.type <span class="sc">==</span> <span class="dv">1</span>, ]</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb32"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>tx0.life <span class="ot"><-</span> <span class="fu">get_life_table</span>(dat.<span class="fl">5.</span>tx0)</span>
|
||||||
|
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>tx0.life</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code># A tibble: 7 × 5
|
||||||
|
fu.interval n.censored n.event n.at.risk hazard.rate
|
||||||
|
<dbl> <int> <int> <int> <dbl>
|
||||||
|
1 0.333 463 49 3378 0.0145
|
||||||
|
2 0.667 253 13 2866 0.00454
|
||||||
|
3 1 340 11 2600 0.00423
|
||||||
|
4 2 591 24 2249 0.0107
|
||||||
|
5 3 568 17 1634 0.0104
|
||||||
|
6 4 521 16 1049 0.0153
|
||||||
|
7 5 501 11 512 0.0215 </code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb34"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>tx1.life <span class="ot"><-</span> <span class="fu">get_life_table</span>(dat.<span class="fl">5.</span>tx1)</span>
|
||||||
|
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>tx1.life</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code># A tibble: 7 × 5
|
||||||
|
fu.interval n.censored n.event n.at.risk hazard.rate
|
||||||
|
<dbl> <int> <int> <int> <dbl>
|
||||||
|
1 0.333 367 103 3225 0.0319
|
||||||
|
2 0.667 238 24 2755 0.00871
|
||||||
|
3 1 273 16 2493 0.00642
|
||||||
|
4 2 573 38 2204 0.0172
|
||||||
|
5 3 575 24 1593 0.0151
|
||||||
|
6 4 532 24 994 0.0241
|
||||||
|
7 5 418 20 438 0.0457 </code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb36"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>tx1.life<span class="sc">$</span>hazard.rate <span class="sc">/</span> tx0.life<span class="sc">$</span>hazard.rate</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>[1] 2.201766 1.920536 1.516975 1.615661 1.448100 1.582998 2.125363</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb38"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>hazard.df <span class="ot"><-</span> <span class="fu">data.frame</span>(</span>
|
||||||
|
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a> <span class="at">fu.interval =</span> tx1.life<span class="sc">$</span>fu.interval,</span>
|
||||||
|
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a> <span class="at">hazard.rate.0 =</span> tx0.life<span class="sc">$</span>hazard.rate,</span>
|
||||||
|
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a> <span class="at">hazard.rate.1 =</span> tx1.life<span class="sc">$</span>hazard.rate,</span>
|
||||||
|
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a> <span class="at">hazard.ratio =</span> tx1.life<span class="sc">$</span>hazard.rate <span class="sc">/</span> tx0.life<span class="sc">$</span>hazard.rate</span>
|
||||||
|
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>) </span>
|
||||||
|
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>(hazard.df, <span class="fu">aes</span>(<span class="at">x =</span> fu.interval)) <span class="sc">+</span></span>
|
||||||
|
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_line</span>(<span class="fu">aes</span>(<span class="at">y =</span> hazard.rate<span class="fl">.0</span>), <span class="at">color =</span> <span class="st">"blue"</span>) <span class="sc">+</span> </span>
|
||||||
|
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_line</span>(<span class="fu">aes</span>(<span class="at">y =</span> hazard.rate<span class="fl">.1</span>), <span class="at">color =</span> <span class="st">"orange"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-15-1.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb39"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot</span>(hazard.df, <span class="fu">aes</span>(<span class="at">x =</span> fu.interval)) <span class="sc">+</span></span>
|
||||||
|
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">geom_line</span>(<span class="fu">aes</span>(<span class="at">y =</span> hazard.ratio))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-15-2.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="exercise-4" class="level2" data-number="1.4">
|
||||||
|
<h2 data-number="1.4" class="anchored" data-anchor-id="exercise-4"><span class="header-section-number">1.4</span> Exercise 4</h2>
|
||||||
|
<p>Show a plot with Kaplan-Meier survival curves for the two donor types.</p>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb40"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>km.tx <span class="ot"><-</span> <span class="fu">survfit</span>(<span class="fu">Surv</span>(follow.up, death) <span class="sc">~</span> tx.type, <span class="at">data =</span> dat[dat<span class="sc">$</span>follow.up <span class="sc"><=</span> <span class="dv">12</span>, ])</span>
|
||||||
|
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a><span class="fu">plot</span>(km.tx, <span class="at">col =</span> <span class="fu">c</span>(<span class="st">"blue"</span>, <span class="st">"orange"</span>))</span>
|
||||||
|
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="fu">legend</span>(<span class="at">legend =</span> <span class="fu">c</span>(<span class="st">"cadaveric"</span>, <span class="st">"living"</span>), <span class="st">"bottomleft"</span>, <span class="at">lwd =</span> <span class="dv">2</span>, <span class="at">col =</span> <span class="fu">c</span>(<span class="st">"blue"</span>, <span class="st">"orange"</span>))</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output-display">
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<p><img src="report_files/figure-html/unnamed-chunk-16-1.png" class="img-fluid figure-img" width="672"></p>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section id="exercise-5" class="level2" data-number="1.5">
|
||||||
|
<h2 data-number="1.5" class="anchored" data-anchor-id="exercise-5"><span class="header-section-number">1.5</span> Exercise 5</h2>
|
||||||
|
<p>Fit a univariate Cox model with predictor donor type. Report the hazard ratio and 95% confidence interval and interpret the result obtained.</p>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb41"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>cox <span class="ot"><-</span> <span class="fu">coxph</span>(<span class="fu">Surv</span>(follow.up, death) <span class="sc">~</span> tx.type, <span class="at">data =</span> dat)</span>
|
||||||
|
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="fu">summary</span>(cox)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>Call:
|
||||||
|
coxph(formula = Surv(follow.up, death) ~ tx.type, data = dat)
|
||||||
|
|
||||||
|
n= 9775, number of events= 465
|
||||||
|
|
||||||
|
coef exp(coef) se(coef) z Pr(>|z|)
|
||||||
|
tx.type 0.64469 1.90539 0.09558 6.745 1.53e-11 ***
|
||||||
|
---
|
||||||
|
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
|
||||||
|
|
||||||
|
exp(coef) exp(-coef) lower .95 upper .95
|
||||||
|
tx.type 1.905 0.5248 1.58 2.298
|
||||||
|
|
||||||
|
Concordance= 0.586 (se = 0.012 )
|
||||||
|
Likelihood ratio test= 47.1 on 1 df, p=7e-12
|
||||||
|
Wald test = 45.5 on 1 df, p=2e-11
|
||||||
|
Score (logrank) test = 47.09 on 1 df, p=7e-12</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb43"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="fl">1.90539</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>[1] 1.90539</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="cell">
|
||||||
|
<div class="sourceCode cell-code" id="cb45"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="fl">1.90539</span> <span class="sc">+</span> <span class="fl">1.96</span> <span class="sc">*</span> <span class="fu">exp</span>(<span class="fl">0.09558</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>[1] 4.061972</code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="sourceCode cell-code" id="cb47"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>(<span class="fl">2.298</span> <span class="sc">-</span> <span class="fl">1.58</span>) <span class="sc">/</span> <span class="dv">2</span> <span class="sc">|></span> <span class="fu">exp</span>() <span class="sc">/</span> <span class="dv">2</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
|
||||||
|
<div class="cell-output cell-output-stdout">
|
||||||
|
<pre><code>[1] 0.04858537</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Exercise 6 — Research shows that an important determinant of mortality after kidney transplant is the age of the recipient. Fit a Cox model with age as predictor and estimate the hazard ratio and its confidence interval. Consider age first as continuous variable and then divide into categories.</p>
|
||||||
|
<p>Exercise 7 — Fit a multivariate Cox model by using other predictors and describe your results.</p>
|
||||||
|
<p>Exercise 8 — Estimate the survival function for specific covariate patterns. Based on the previous results choose the best predictors.</p>
|
||||||
|
<p>Exercise 9 — Check the proportional hazards assumption. You may use the function cox.zph. Discuss the result and possible implications. Exercise 10 — Plot the Schoenfeld residuals and comment.</p>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<!-- /main column -->
|
||||||
|
<script id="quarto-html-after-body" type="application/javascript">
|
||||||
|
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||||||
|
const icon = "";
|
||||||
|
const anchorJS = new window.AnchorJS();
|
||||||
|
anchorJS.options = {
|
||||||
|
placement: 'right',
|
||||||
|
icon: icon
|
||||||
|
};
|
||||||
|
anchorJS.add('.anchored');
|
||||||
|
const isCodeAnnotation = (el) => {
|
||||||
|
for (const clz of el.classList) {
|
||||||
|
if (clz.startsWith('code-annotation-')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const onCopySuccess = function(e) {
|
||||||
|
// button target
|
||||||
|
const button = e.trigger;
|
||||||
|
// don't keep focus
|
||||||
|
button.blur();
|
||||||
|
// flash "checked"
|
||||||
|
button.classList.add('code-copy-button-checked');
|
||||||
|
var currentTitle = button.getAttribute("title");
|
||||||
|
button.setAttribute("title", "Copied!");
|
||||||
|
let tooltip;
|
||||||
|
if (window.bootstrap) {
|
||||||
|
button.setAttribute("data-bs-toggle", "tooltip");
|
||||||
|
button.setAttribute("data-bs-placement", "left");
|
||||||
|
button.setAttribute("data-bs-title", "Copied!");
|
||||||
|
tooltip = new bootstrap.Tooltip(button,
|
||||||
|
{ trigger: "manual",
|
||||||
|
customClass: "code-copy-button-tooltip",
|
||||||
|
offset: [0, -8]});
|
||||||
|
tooltip.show();
|
||||||
|
}
|
||||||
|
setTimeout(function() {
|
||||||
|
if (tooltip) {
|
||||||
|
tooltip.hide();
|
||||||
|
button.removeAttribute("data-bs-title");
|
||||||
|
button.removeAttribute("data-bs-toggle");
|
||||||
|
button.removeAttribute("data-bs-placement");
|
||||||
|
}
|
||||||
|
button.setAttribute("title", currentTitle);
|
||||||
|
button.classList.remove('code-copy-button-checked');
|
||||||
|
}, 1000);
|
||||||
|
// clear code selection
|
||||||
|
e.clearSelection();
|
||||||
|
}
|
||||||
|
const getTextToCopy = function(trigger) {
|
||||||
|
const codeEl = trigger.previousElementSibling.cloneNode(true);
|
||||||
|
for (const childEl of codeEl.children) {
|
||||||
|
if (isCodeAnnotation(childEl)) {
|
||||||
|
childEl.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codeEl.innerText;
|
||||||
|
}
|
||||||
|
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
|
||||||
|
text: getTextToCopy
|
||||||
|
});
|
||||||
|
clipboard.on('success', onCopySuccess);
|
||||||
|
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
|
||||||
|
const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
|
||||||
|
text: getTextToCopy,
|
||||||
|
container: window.document.getElementById('quarto-embedded-source-code-modal')
|
||||||
|
});
|
||||||
|
clipboardModal.on('success', onCopySuccess);
|
||||||
|
}
|
||||||
|
var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
|
||||||
|
var mailtoRegex = new RegExp(/^mailto:/);
|
||||||
|
var filterRegex = new RegExp('/' + window.location.host + '/');
|
||||||
|
var isInternal = (href) => {
|
||||||
|
return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
|
||||||
|
}
|
||||||
|
// Inspect non-navigation links and adorn them if external
|
||||||
|
var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
|
||||||
|
for (var i=0; i<links.length; i++) {
|
||||||
|
const link = links[i];
|
||||||
|
if (!isInternal(link.href)) {
|
||||||
|
// undo the damage that might have been done by quarto-nav.js in the case of
|
||||||
|
// links that we want to consider external
|
||||||
|
if (link.dataset.originalHref !== undefined) {
|
||||||
|
link.href = link.dataset.originalHref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
|
||||||
|
const config = {
|
||||||
|
allowHTML: true,
|
||||||
|
maxWidth: 500,
|
||||||
|
delay: 100,
|
||||||
|
arrow: false,
|
||||||
|
appendTo: function(el) {
|
||||||
|
return el.parentElement;
|
||||||
|
},
|
||||||
|
interactive: true,
|
||||||
|
interactiveBorder: 10,
|
||||||
|
theme: 'quarto',
|
||||||
|
placement: 'bottom-start',
|
||||||
|
};
|
||||||
|
if (contentFn) {
|
||||||
|
config.content = contentFn;
|
||||||
|
}
|
||||||
|
if (onTriggerFn) {
|
||||||
|
config.onTrigger = onTriggerFn;
|
||||||
|
}
|
||||||
|
if (onUntriggerFn) {
|
||||||
|
config.onUntrigger = onUntriggerFn;
|
||||||
|
}
|
||||||
|
window.tippy(el, config);
|
||||||
|
}
|
||||||
|
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
|
||||||
|
for (var i=0; i<noterefs.length; i++) {
|
||||||
|
const ref = noterefs[i];
|
||||||
|
tippyHover(ref, function() {
|
||||||
|
// use id or data attribute instead here
|
||||||
|
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
|
||||||
|
try { href = new URL(href).hash; } catch {}
|
||||||
|
const id = href.replace(/^#\/?/, "");
|
||||||
|
const note = window.document.getElementById(id);
|
||||||
|
if (note) {
|
||||||
|
return note.innerHTML;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const xrefs = window.document.querySelectorAll('a.quarto-xref');
|
||||||
|
const processXRef = (id, note) => {
|
||||||
|
// Strip column container classes
|
||||||
|
const stripColumnClz = (el) => {
|
||||||
|
el.classList.remove("page-full", "page-columns");
|
||||||
|
if (el.children) {
|
||||||
|
for (const child of el.children) {
|
||||||
|
stripColumnClz(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stripColumnClz(note)
|
||||||
|
if (id === null || id.startsWith('sec-')) {
|
||||||
|
// Special case sections, only their first couple elements
|
||||||
|
const container = document.createElement("div");
|
||||||
|
if (note.children && note.children.length > 2) {
|
||||||
|
container.appendChild(note.children[0].cloneNode(true));
|
||||||
|
for (let i = 1; i < note.children.length; i++) {
|
||||||
|
const child = note.children[i];
|
||||||
|
if (child.tagName === "P" && child.innerText === "") {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
container.appendChild(child.cloneNode(true));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (window.Quarto?.typesetMath) {
|
||||||
|
window.Quarto.typesetMath(container);
|
||||||
|
}
|
||||||
|
return container.innerHTML
|
||||||
|
} else {
|
||||||
|
if (window.Quarto?.typesetMath) {
|
||||||
|
window.Quarto.typesetMath(note);
|
||||||
|
}
|
||||||
|
return note.innerHTML;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Remove any anchor links if they are present
|
||||||
|
const anchorLink = note.querySelector('a.anchorjs-link');
|
||||||
|
if (anchorLink) {
|
||||||
|
anchorLink.remove();
|
||||||
|
}
|
||||||
|
if (window.Quarto?.typesetMath) {
|
||||||
|
window.Quarto.typesetMath(note);
|
||||||
|
}
|
||||||
|
if (note.classList.contains("callout")) {
|
||||||
|
return note.outerHTML;
|
||||||
|
} else {
|
||||||
|
return note.innerHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i=0; i<xrefs.length; i++) {
|
||||||
|
const xref = xrefs[i];
|
||||||
|
tippyHover(xref, undefined, function(instance) {
|
||||||
|
instance.disable();
|
||||||
|
let url = xref.getAttribute('href');
|
||||||
|
let hash = undefined;
|
||||||
|
if (url.startsWith('#')) {
|
||||||
|
hash = url;
|
||||||
|
} else {
|
||||||
|
try { hash = new URL(url).hash; } catch {}
|
||||||
|
}
|
||||||
|
if (hash) {
|
||||||
|
const id = hash.replace(/^#\/?/, "");
|
||||||
|
const note = window.document.getElementById(id);
|
||||||
|
if (note !== null) {
|
||||||
|
try {
|
||||||
|
const html = processXRef(id, note.cloneNode(true));
|
||||||
|
instance.setContent(html);
|
||||||
|
} finally {
|
||||||
|
instance.enable();
|
||||||
|
instance.show();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// See if we can fetch this
|
||||||
|
fetch(url.split('#')[0])
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(html => {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const htmlDoc = parser.parseFromString(html, "text/html");
|
||||||
|
const note = htmlDoc.getElementById(id);
|
||||||
|
if (note !== null) {
|
||||||
|
const html = processXRef(id, note);
|
||||||
|
instance.setContent(html);
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
instance.enable();
|
||||||
|
instance.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// See if we can fetch a full url (with no hash to target)
|
||||||
|
// This is a special case and we should probably do some content thinning / targeting
|
||||||
|
fetch(url)
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(html => {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const htmlDoc = parser.parseFromString(html, "text/html");
|
||||||
|
const note = htmlDoc.querySelector('main.content');
|
||||||
|
if (note !== null) {
|
||||||
|
// This should only happen for chapter cross references
|
||||||
|
// (since there is no id in the URL)
|
||||||
|
// remove the first header
|
||||||
|
if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
|
||||||
|
note.children[0].remove();
|
||||||
|
}
|
||||||
|
const html = processXRef(null, note);
|
||||||
|
instance.setContent(html);
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
instance.enable();
|
||||||
|
instance.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(instance) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let selectedAnnoteEl;
|
||||||
|
const selectorForAnnotation = ( cell, annotation) => {
|
||||||
|
let cellAttr = 'data-code-cell="' + cell + '"';
|
||||||
|
let lineAttr = 'data-code-annotation="' + annotation + '"';
|
||||||
|
const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
const selectCodeLines = (annoteEl) => {
|
||||||
|
const doc = window.document;
|
||||||
|
const targetCell = annoteEl.getAttribute("data-target-cell");
|
||||||
|
const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
|
||||||
|
const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
|
||||||
|
const lines = annoteSpan.getAttribute("data-code-lines").split(",");
|
||||||
|
const lineIds = lines.map((line) => {
|
||||||
|
return targetCell + "-" + line;
|
||||||
|
})
|
||||||
|
let top = null;
|
||||||
|
let height = null;
|
||||||
|
let parent = null;
|
||||||
|
if (lineIds.length > 0) {
|
||||||
|
//compute the position of the single el (top and bottom and make a div)
|
||||||
|
const el = window.document.getElementById(lineIds[0]);
|
||||||
|
top = el.offsetTop;
|
||||||
|
height = el.offsetHeight;
|
||||||
|
parent = el.parentElement.parentElement;
|
||||||
|
if (lineIds.length > 1) {
|
||||||
|
const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
|
||||||
|
const bottom = lastEl.offsetTop + lastEl.offsetHeight;
|
||||||
|
height = bottom - top;
|
||||||
|
}
|
||||||
|
if (top !== null && height !== null && parent !== null) {
|
||||||
|
// cook up a div (if necessary) and position it
|
||||||
|
let div = window.document.getElementById("code-annotation-line-highlight");
|
||||||
|
if (div === null) {
|
||||||
|
div = window.document.createElement("div");
|
||||||
|
div.setAttribute("id", "code-annotation-line-highlight");
|
||||||
|
div.style.position = 'absolute';
|
||||||
|
parent.appendChild(div);
|
||||||
|
}
|
||||||
|
div.style.top = top - 2 + "px";
|
||||||
|
div.style.height = height + 4 + "px";
|
||||||
|
div.style.left = 0;
|
||||||
|
let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
|
||||||
|
if (gutterDiv === null) {
|
||||||
|
gutterDiv = window.document.createElement("div");
|
||||||
|
gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
|
||||||
|
gutterDiv.style.position = 'absolute';
|
||||||
|
const codeCell = window.document.getElementById(targetCell);
|
||||||
|
const gutter = codeCell.querySelector('.code-annotation-gutter');
|
||||||
|
gutter.appendChild(gutterDiv);
|
||||||
|
}
|
||||||
|
gutterDiv.style.top = top - 2 + "px";
|
||||||
|
gutterDiv.style.height = height + 4 + "px";
|
||||||
|
}
|
||||||
|
selectedAnnoteEl = annoteEl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const unselectCodeLines = () => {
|
||||||
|
const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
|
||||||
|
elementsIds.forEach((elId) => {
|
||||||
|
const div = window.document.getElementById(elId);
|
||||||
|
if (div) {
|
||||||
|
div.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
selectedAnnoteEl = undefined;
|
||||||
|
};
|
||||||
|
// Handle positioning of the toggle
|
||||||
|
window.addEventListener(
|
||||||
|
"resize",
|
||||||
|
throttle(() => {
|
||||||
|
elRect = undefined;
|
||||||
|
if (selectedAnnoteEl) {
|
||||||
|
selectCodeLines(selectedAnnoteEl);
|
||||||
|
}
|
||||||
|
}, 10)
|
||||||
|
);
|
||||||
|
function throttle(fn, ms) {
|
||||||
|
let throttle = false;
|
||||||
|
let timer;
|
||||||
|
return (...args) => {
|
||||||
|
if(!throttle) { // first call gets through
|
||||||
|
fn.apply(this, args);
|
||||||
|
throttle = true;
|
||||||
|
} else { // all the others get throttled
|
||||||
|
if(timer) clearTimeout(timer); // cancel #2
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
fn.apply(this, args);
|
||||||
|
timer = throttle = false;
|
||||||
|
}, ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Attach click handler to the DT
|
||||||
|
const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
|
||||||
|
for (const annoteDlNode of annoteDls) {
|
||||||
|
annoteDlNode.addEventListener('click', (event) => {
|
||||||
|
const clickedEl = event.target;
|
||||||
|
if (clickedEl !== selectedAnnoteEl) {
|
||||||
|
unselectCodeLines();
|
||||||
|
const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
|
||||||
|
if (activeEl) {
|
||||||
|
activeEl.classList.remove('code-annotation-active');
|
||||||
|
}
|
||||||
|
selectCodeLines(clickedEl);
|
||||||
|
clickedEl.classList.add('code-annotation-active');
|
||||||
|
} else {
|
||||||
|
// Unselect the line
|
||||||
|
unselectCodeLines();
|
||||||
|
clickedEl.classList.remove('code-annotation-active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const findCites = (el) => {
|
||||||
|
const parentEl = el.parentElement;
|
||||||
|
if (parentEl) {
|
||||||
|
const cites = parentEl.dataset.cites;
|
||||||
|
if (cites) {
|
||||||
|
return {
|
||||||
|
el,
|
||||||
|
cites: cites.split(' ')
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return findCites(el.parentElement)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
|
||||||
|
for (var i=0; i<bibliorefs.length; i++) {
|
||||||
|
const ref = bibliorefs[i];
|
||||||
|
const citeInfo = findCites(ref);
|
||||||
|
if (citeInfo) {
|
||||||
|
tippyHover(citeInfo.el, function() {
|
||||||
|
var popup = window.document.createElement('div');
|
||||||
|
citeInfo.cites.forEach(function(cite) {
|
||||||
|
var citeDiv = window.document.createElement('div');
|
||||||
|
citeDiv.classList.add('hanging-indent');
|
||||||
|
citeDiv.classList.add('csl-entry');
|
||||||
|
var biblioDiv = window.document.getElementById('ref-' + cite);
|
||||||
|
if (biblioDiv) {
|
||||||
|
citeDiv.innerHTML = biblioDiv.innerHTML;
|
||||||
|
}
|
||||||
|
popup.appendChild(citeDiv);
|
||||||
|
});
|
||||||
|
return popup.innerHTML;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div> <!-- /content -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue