This repository has been archived by the owner on Jun 29, 2022. It is now read-only.
generated from tlverse/tlverse-workshops
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path05-tmle3.html
327 lines (295 loc) · 22.1 KB
/
05-tmle3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>05-tmle3.knit</title>
<meta name="generator" content="placeholder" />
<meta property="og:title" content="05-tmle3.knit" />
<meta property="og:type" content="book" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="05-tmle3.knit" />
<!-- JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.6/clipboard.min.js" integrity="sha256-inc5kl9MA1hkeYUt+EC3BhlIgyp/2jDIyBLS6k3UxPI=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/6.4.6/fuse.js" integrity="sha512-zv6Ywkjyktsohkbp9bb45V6tEMoWhzFzXis+LrMehmJZZSys19Yxf1dopHx7WzIKxr5tK2dVcYmaCk2uqdjF4A==" crossorigin="anonymous"></script>
<script src="https://kit.fontawesome.com/6ecbd6c532.js" crossorigin="anonymous"></script>
<script src="libs/header-attrs-2.11/header-attrs.js"></script>
<script src="libs/jquery-3.6.0/jquery-3.6.0.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link href="libs/bootstrap-4.6.0/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap-4.6.0/bootstrap.bundle.min.js"></script>
<script src="libs/bs3compat-0.3.1/transition.js"></script>
<script src="libs/bs3compat-0.3.1/tabs.js"></script>
<script src="libs/bs3compat-0.3.1/bs3compat.js"></script>
<link href="libs/bs4_book-1.0.0/bs4_book.css" rel="stylesheet" />
<script src="libs/bs4_book-1.0.0/bs4_book.js"></script>
<span class="math inline">
\(\DeclareMathOperator{\expit}{expit}\)
\(\DeclareMathOperator{\logit}{logit}\)
\(\DeclareMathOperator*{\argmin}{\arg\!\min}\)
\(\newcommand{\indep}{\perp\!\!\!\perp}\)
\(\newcommand{\coloneqq}{\mathrel{=}}\)
\(\newcommand{\R}{\mathbb{R}}\)
\(\newcommand{\E}{\mathbb{E}}\)
\(\newcommand{\M}{\mathcal{M}}\)
\(\renewcommand{\P}{\mathbb{P}}\)
\(\newcommand{\I}{\mathbb{I}}\)
\(\newcommand{\1}{\mathbbm{1}}\)
</span>
<script src="https://cdnjs.cloudflare.com/ajax/libs/autocomplete.js/0.38.0/autocomplete.jquery.min.js" integrity="sha512-GU9ayf+66Xx2TmpxqJpliWbT5PiGYxpaG8rfnBEk1LL8l1KGkRShhngwdXK1UgqhAzWpZHSiYPc09/NwDQIGyg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js" integrity="sha512-5CYOlHXGh6QpOFA/TeTylKLWfB3ftPsde7AnmhuitiTX4K5SqCLBeKro6sPS8ilsz1Q4NRx3v8Ko2IBiszzdww==" crossorigin="anonymous"></script>
<!-- CSS -->
</head>
<body data-spy="scroll" data-target="#toc">
<div class="container-fluid">
<!--bookdown:title:start-->
<!--bookdown:title:end-->
<!--bookdown:toc:start-->
<div class="row">
<header class="col-sm-12 col-lg-3 sidebar sidebar-book">
<a class="sr-only sr-only-focusable" href="#content">Skip to main content</a>
<div class="d-flex align-items-start justify-content-between">
<h1>
<a href="index.html" title=""></a>
</h1>
<button class="btn btn-outline-primary d-lg-none ml-2 mt-1" type="button" data-toggle="collapse" data-target="#main-nav" aria-expanded="true" aria-controls="main-nav"><i class="fas fa-bars"></i><span class="sr-only">Show table of contents</span></button>
</div>
<div id="main-nav" class="collapse-lg">
<form role="search">
<input id="search" class="form-control" type="search" placeholder="Search" aria-label="Search">
</form>
<nav aria-label="Table of contents">
<h2>Table of contents</h2>
<div id="book-toc"></div>
<div class="book-extra">
<p><a id="book-repo" href="#">View book source <i class="fab fa-github"></i></a></li></p>
</div>
</nav>
</div>
</header>
<main class="col-sm-12 col-md-9 col-lg-7" id="content">
<!--bookdown:toc:end-->
<!--bookdown:body:start-->
<div id="tmle3" class="section level1" number="1">
<h1><span class="header-section-number">1</span> The TMLE Framework (Brief Review)</h1>
<p><em>Jeremy Coyle</em> and <em>Nima Hejazi</em></p>
<p>Based on the <a href="https://github.com/tlverse/tmle3"><code>tmle3</code> <code>R</code> package</a>.</p>
<div id="learn-tmle" class="section level2" number="1.1">
<h2><span class="header-section-number">1.1</span> Learning Objectives</h2>
<p>By the end of this chapter, you will be able to</p>
<ol style="list-style-type: decimal">
<li>Use <code>tmle3</code> to estimate an Average Treatment Effect (ATE).</li>
<li>Understand how to use <code>tmle3</code> “Specs” objects.</li>
</ol>
</div>
<div id="tmle-intro" class="section level2" number="1.2">
<h2><span class="header-section-number">1.2</span> Introduction</h2>
<p>Mark and Alan introduced the core concepts associated with TMLE in their intro talk. Today, we’ll be focused on some more advanced applications of <code>tmle3</code>, but we’d like to review the basics of how to use the package. Before we do that, are there any conceptual clarifications on TMLE?</p>
<p>The following sections describe a simple way of
specifying and estimating a TMLE in the <code>tlverse</code>. In designing <code>tmle3</code>, we
sought to replicate as closely as possible the very general estimation framework
of TMLE, and so each theoretical object relevant to TMLE is encoded in a
corresponding software object/method. More information on this design can be found in the <a href="http://tlverse.org/tlverse-handbook/tmle3.html#tmle3-components">handbook</a>.</p>
</div>
<div id="easy-bake-example-tmle3-for-ate" class="section level2" number="1.3">
<h2><span class="header-section-number">1.3</span> Easy-Bake Example: <code>tmle3</code> for ATE</h2>
<p>We’ll illustrate the most basic use of TMLE using the WASH Benefits data
introduced earlier and estimating an average treatment effect. Similar specifications will be relevant during the later sections on advanced <code>tmle3</code> usage.</p>
<div id="load-the-data" class="section level3" number="1.3.1">
<h3><span class="header-section-number">1.3.1</span> Load the Data</h3>
<p>We’ll use the same WASH Benefits data as the earlier chapters:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(data.table)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(dplyr)</span></code></pre></div>
<pre><code>##
## Attaching package: 'dplyr'</code></pre>
<pre><code>## The following objects are masked from 'package:data.table':
##
## between, first, last</code></pre>
<pre><code>## The following objects are masked from 'package:stats':
##
## filter, lag</code></pre>
<pre><code>## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union</code></pre>
<div class="sourceCode" id="cb6"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(tmle3)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="fu">library</span>(sl3)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>washb_data <span class="ot"><-</span> <span class="fu">fread</span>(</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">paste0</span>(</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> <span class="st">"https://raw.githubusercontent.com/tlverse/tlverse-data/master/"</span>,</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> <span class="st">"wash-benefits/washb_data.csv"</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a> ),</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> <span class="at">stringsAsFactors =</span> <span class="cn">TRUE</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>)</span></code></pre></div>
</div>
<div id="define-the-variable-roles" class="section level3" number="1.3.2">
<h3><span class="header-section-number">1.3.2</span> Define the variable roles</h3>
<p>We’ll use the common <span class="math inline">\(W\)</span> (covariates), <span class="math inline">\(A\)</span> (treatment/intervention), <span class="math inline">\(Y\)</span>
(outcome) data structure. <code>tmle3</code> needs to know what variables in the dataset
correspond to each of these roles. We use a list of character vectors to tell
it. We call this a “Node List” as it corresponds to the nodes in a Directed
Acyclic Graph (DAG), a way of displaying causal relationships between variables.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>node_list <span class="ot"><-</span> <span class="fu">list</span>(</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> <span class="at">W =</span> <span class="fu">c</span>(</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> <span class="st">"month"</span>, <span class="st">"aged"</span>, <span class="st">"sex"</span>, <span class="st">"momage"</span>, <span class="st">"momedu"</span>,</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> <span class="st">"momheight"</span>, <span class="st">"hfiacat"</span>, <span class="st">"Nlt18"</span>, <span class="st">"Ncomp"</span>, <span class="st">"watmin"</span>,</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> <span class="st">"elec"</span>, <span class="st">"floor"</span>, <span class="st">"walls"</span>, <span class="st">"roof"</span>, <span class="st">"asset_wardrobe"</span>,</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> <span class="st">"asset_table"</span>, <span class="st">"asset_chair"</span>, <span class="st">"asset_khat"</span>,</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <span class="st">"asset_chouki"</span>, <span class="st">"asset_tv"</span>, <span class="st">"asset_refrig"</span>,</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> <span class="st">"asset_bike"</span>, <span class="st">"asset_moto"</span>, <span class="st">"asset_sewmach"</span>,</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"asset_mobile"</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> ),</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> <span class="at">A =</span> <span class="st">"tr"</span>,</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a> <span class="at">Y =</span> <span class="st">"whz"</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a>)</span></code></pre></div>
</div>
<div id="handle-missingness" class="section level3" number="1.3.3">
<h3><span class="header-section-number">1.3.3</span> Handle Missingness</h3>
<p>Currently, missingness in <code>tmle3</code> is handled in a fairly simple way:</p>
<ul>
<li>Missing covariates are median- (for continuous) or mode- (for discrete)
imputed, and additional covariates indicating imputation are generated, just
as described in <a href="#sl3">the <code>sl3</code> chapter</a>.</li>
<li>Missing treatment variables are excluded – such observations are dropped.</li>
<li>Missing outcomes are efficiently handled by the automatic calculation (and
incorporation into estimators) of <em>inverse probability of censoring weights</em>
(IPCW); this is also known as IPCW-TMLE and may be thought of as a joint
intervention to remove missingness and is analogous to the procedure used with
classical inverse probability weighted estimators.</li>
</ul>
<p>These steps are implemented in the <code>process_missing</code> function in <code>tmle3</code>:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>processed <span class="ot"><-</span> <span class="fu">process_missing</span>(washb_data, node_list)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>washb_data <span class="ot"><-</span> processed<span class="sc">$</span>data</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>node_list <span class="ot"><-</span> processed<span class="sc">$</span>node_list</span></code></pre></div>
</div>
<div id="create-a-spec-object" class="section level3" number="1.3.4">
<h3><span class="header-section-number">1.3.4</span> Create a “Spec” Object</h3>
<p><code>tmle3</code> is general, and allows most components of the TMLE procedure to be
specified in a modular way. However, most end-users will not be interested in
manually specifying all of these components. Therefore, <code>tmle3</code> implements a
<code>tmle3_Spec</code> object that bundles a set of components into a <em>specification</em>
(“Spec”) that, with minimal additional detail, can be run by an end-user.</p>
<p>We’ll start with using one of the specs, and then work our way down into the
internals of <code>tmle3</code>.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>ate_spec <span class="ot"><-</span> <span class="fu">tmle_ATE</span>(</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> <span class="at">treatment_level =</span> <span class="st">"Nutrition + WSH"</span>,</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <span class="at">control_level =</span> <span class="st">"Control"</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>)</span></code></pre></div>
</div>
<div id="define-the-learners" class="section level3" number="1.3.5">
<h3><span class="header-section-number">1.3.5</span> Define the learners</h3>
<p>Currently, the only other thing a user must define are the <code>sl3</code> learners used
to estimate the relevant factors of the likelihood: Q and g.</p>
<p>This takes the form of a list of <code>sl3</code> learners, one for each likelihood factor
to be estimated with <code>sl3</code>:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co"># choose base learners</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>lrnr_mean <span class="ot"><-</span> <span class="fu">make_learner</span>(Lrnr_mean)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>lrnr_rf <span class="ot"><-</span> <span class="fu">make_learner</span>(Lrnr_ranger)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co"># define metalearners appropriate to data types</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>ls_metalearner <span class="ot"><-</span> <span class="fu">make_learner</span>(Lrnr_nnls)</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>mn_metalearner <span class="ot"><-</span> <span class="fu">make_learner</span>(</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a> Lrnr_solnp, metalearner_linear_multinomial,</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a> loss_loglik_multinomial</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>sl_Y <span class="ot"><-</span> Lrnr_sl<span class="sc">$</span><span class="fu">new</span>(</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a> <span class="at">learners =</span> <span class="fu">list</span>(lrnr_mean, lrnr_rf),</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a> <span class="at">metalearner =</span> ls_metalearner</span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>sl_A <span class="ot"><-</span> Lrnr_sl<span class="sc">$</span><span class="fu">new</span>(</span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a> <span class="at">learners =</span> <span class="fu">list</span>(lrnr_mean, lrnr_rf),</span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a> <span class="at">metalearner =</span> mn_metalearner</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>learner_list <span class="ot"><-</span> <span class="fu">list</span>(<span class="at">A =</span> sl_A, <span class="at">Y =</span> sl_Y)</span></code></pre></div>
<p>Here, we use a Super Learner as defined in the previous chapter. In the future,
we plan to include reasonable defaults learners.</p>
</div>
<div id="fit-the-tmle" class="section level3" number="1.3.6">
<h3><span class="header-section-number">1.3.6</span> Fit the TMLE</h3>
<p>We now have everything we need to fit the tmle using <code>tmle3</code>:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>tmle_fit <span class="ot"><-</span> <span class="fu">tmle3</span>(ate_spec, washb_data, node_list, learner_list)</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="fu">print</span>(tmle_fit)</span></code></pre></div>
<pre><code>## A tmle3_Fit that took 1 step(s)
## type param init_est tmle_est
## 1: ATE ATE[Y_{A=Nutrition + WSH}-Y_{A=Control}] -0.004847046 0.01392972
## se lower upper psi_transformed lower_transformed
## 1: 0.05027517 -0.0846078 0.1124672 0.01392972 -0.0846078
## upper_transformed
## 1: 0.1124672</code></pre>
</div>
<div id="evaluate-the-estimates" class="section level3" number="1.3.7">
<h3><span class="header-section-number">1.3.7</span> Evaluate the Estimates</h3>
<p>We can see the summary results by printing the fit object. Alternatively, we
can extra results from the summary by indexing into it:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>estimates <span class="ot"><-</span> tmle_fit<span class="sc">$</span>summary<span class="sc">$</span>psi_transformed</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="fu">print</span>(estimates)</span></code></pre></div>
<pre><code>## [1] 0.01392972</code></pre>
</div>
</div>
<div id="summary" class="section level2" number="1.4">
<h2><span class="header-section-number">1.4</span> Summary</h2>
<p><code>tmle3</code> is a general purpose framework for generating TML estimates. The easiest
way to use it is to use a predefined spec, allowing you to just fill in the
blanks for the data, variable roles, and <code>sl3</code> learners. In the next sections,
we’ll see how this framework can be used to estimate advanced parameters such as
optimal treatments and stochastic shift interventions.</p>
<p>There are no exercises for this brief chapter, but you may find the exercises in the corresponding handbook chapter helpful.</p>
</div>
</div>
<!--bookdown:body:end-->
</main>
<div class="col-md-3 col-lg-2 d-none d-md-block sidebar sidebar-chapter">
<nav id="toc" data-toggle="toc" aria-label="On this page">
<h2>On this page</h2>
<div id="book-on-this-page"></div>
<div class="book-extra">
<ul class="list-unstyled">
<li><a id="book-source" href="#">View source <i class="fab fa-github"></i></a></li>
<li><a id="book-edit" href="#">Edit this page <i class="fab fa-github"></i></a></li>
</ul>
</div>
</nav>
</div>
</div>
</div> <!-- .container -->
<footer class="bg-primary text-light mt-5">
<div class="container"><div class="row">
<div class="col-12 col-md-6 mt-3">
<p>"<strong></strong>" was written by . </p>
</div>
<div class="col-12 col-md-6 mt-3">
<p>This book was built by the <a class="text-light" href="https://bookdown.org">bookdown</a> R package.</p>
</div>
</div></div>
</footer>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
var src = "true";
if (src === "" || src === "true") src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML";
if (location.protocol !== "file:")
if (/^https?:/.test(src))
src = src.replace(/^https?:/, '');
script.src = src;
document.getElementsByTagName("head")[0].appendChild(script);
})();
</script>
<script type="text/x-mathjax-config">const popovers = document.querySelectorAll('a.footnote-ref[data-toggle="popover"]');
for (let popover of popovers) {
const div = document.createElement('div');
div.setAttribute('style', 'position: absolute; top: 0, left:0; width:0, height:0, overflow: hidden; visibility: hidden;');
div.innerHTML = popover.getAttribute('data-content');
var has_math = div.querySelector("span.math");
if (has_math) {
document.body.appendChild(div);
MathJax.Hub.Queue(["Typeset", MathJax.Hub, div]);
MathJax.Hub.Queue(function() {
popover.setAttribute('data-content', div.innerHTML);
document.body.removeChild(div);
})
}
}
</script>
</body>
</html>