-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
407 lines (389 loc) · 27.2 KB
/
index.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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
<!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.2.335">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>index</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 -1.6em;
vertical-align: middle;
}
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;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
div.csl-bib-body { }
div.csl-entry {
clear: both;
}
.hanging div.csl-entry {
margin-left:2em;
text-indent:-2em;
}
div.csl-left-margin {
min-width:2em;
float:left;
}
div.csl-right-inline {
margin-left:2em;
padding-left:1em;
}
div.csl-indent {
margin-left: 2em;
}
</style>
<script src="index_files/libs/clipboard/clipboard.min.js"></script>
<script src="index_files/libs/quarto-html/quarto.js"></script>
<script src="index_files/libs/quarto-html/popper.min.js"></script>
<script src="index_files/libs/quarto-html/tippy.umd.min.js"></script>
<script src="index_files/libs/quarto-html/anchor.min.js"></script>
<link href="index_files/libs/quarto-html/tippy.css" rel="stylesheet">
<link href="index_files/libs/quarto-html/quarto-syntax-highlighting.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="index_files/libs/bootstrap/bootstrap.min.js"></script>
<link href="index_files/libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="index_files/libs/bootstrap/bootstrap.min.css" rel="stylesheet" id="quarto-bootstrap" data-mode="light">
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
</head>
<body class="fullcontent">
<div id="quarto-content" class="page-columns page-rows-contents page-layout-article">
<main class="content" id="quarto-document-content">
<section id="julia-introduction" class="level1">
<h1>Julia introduction</h1>
<p>This is a collection of notes for using <code>Julia</code> for introductory statistics.</p>
<p>In case you haven’t heard, <a href="https://julialang.org/">Julia</a> is an open-source programming language suitable for many tasks, like scientific programming. It is designed for high performance – Julia programs compile on the fly to efficient native code. Julia has a relatively easy to learn syntax for many tasks, certainly no harder to pick up than <code>R</code> and <code>Python</code>, widely used scripting languages for the tasks illustrated herein.</p>
<p>Why these notes on introductory statistics? No compelling reason save I had done something similar for <code>R</code> when <code>R</code> was a fledgling <code>S-Plus</code> clone. No more, <code>R</code> is a juggernaut, and it is almost certain <code>Julia</code> will never replace <code>R</code> as the programming langauage of choice for statistics. Besides, <code>Julia</code> users can already interface with <code>R</code> quite easily through <code>RCall</code>. <em>However</em>, there are some reasons that <code>Julia</code> could be a useful language when learning basic inferential statistics, especially if other real strengths of the <code>Julia</code> ecosystem were needed. So these notes show how <code>Julia</code> can be used for these tasks, and, hopefully, shows that it works pretty well.</p>
<p>There are some great books published about using <code>Julia</code> <span class="citation" data-cites="bezanson2017julia">(<a href="#ref-bezanson2017julia" role="doc-biblioref">Bezanson et al. 2017</a>)</span> with data science, within which much of this material is covered. For example, <span class="citation" data-cites="JuliaForDataAnalysis">(<a href="#ref-JuliaForDataAnalysis" role="doc-biblioref">Kamiński 2022</a>)</span> is a quite thorough treatmeant, <span class="citation" data-cites="storopolihuijzeralonso2021juliadatascience">(<a href="#ref-storopolihuijzeralonso2021juliadatascience" role="doc-biblioref">Storopoli et al. 2021</a>)</span> is very well done, <span class="citation" data-cites="nazarathy2021statisticsjulia">(<a href="#ref-nazarathy2021statisticsjulia" role="doc-biblioref">Nazarathy and Klok 2021</a>)</span> covers topics here (cf. the <a href="https://www.youtube.com/watch?v=IlPoU5Yr2QI">JuliaCon Workshop</a>). The quarto book <a href="https://juliamixedmodels.github.io/EmbraceUncertainty/">Embrace Uncertainty</a> <span class="citation" data-cites="Embrace-Uncertainty-Fitting-Mixed-Effects-Models-with-Julia">(<a href="#ref-Embrace-Uncertainty-Fitting-Mixed-Effects-Models-with-Julia" role="doc-biblioref">Alday et al. 2022</a>)</span> covers the more advanced topic of Mixed-effects Models in <code>Julia</code>. Nothing here couldn’t be found in those resources, these notes are just an introduction.</p>
<div class="callout-note callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Contribute
</div>
</div>
<div class="callout-body-container callout-body">
<p>These notes are a work in progress. Feel free to click the “edit this page” button or report an issue.</p>
</div>
</div>
<section id="installing-and-running-julia" class="level2">
<h2 class="anchored" data-anchor-id="installing-and-running-julia">Installing and running Julia</h2>
<p><code>Julia</code> can be downloaded from <a href="https://julialang.org/">julialang.org</a>. The language is evolving rapidly. The latest official release is recommended. These notes should work with any version since <code>v"1.6.0"</code>. It is recommended to use a version <code>v"1.9.0"</code> or later, as there are significant speedups with external packages that make the user experience even better.</p>
<p>Once downloaded and installed the <code>Julia</code> installation will provide a <em>command line</em> for interactive usage and a binary to run scripts. It is envisioned most users will use an alternative interface, though <code>Julia</code> has an excellent REPL for command-line usage.</p>
<p>Some alternatives to the REPL for interacting with <code>Julia</code> are:</p>
<ul>
<li><a href="https://github.com/JuliaLang/IJulia.jl">IJulia</a>: This is a means to use the Jupyter interactive environment to interact with <code>Julia</code> through notebooks. It is made available by installing the package <code>IJulia</code> (details on package installation follow below). This relies on <code>Julia</code>’s seamless interaction with <code>Python</code> and leverages many technologies developed for that langauge.</li>
<li><a href="https://githuhttps://plutojl.org/">Pluto</a>: The Pluto environment provides a notebook interface for <code>Julia</code> written in <code>Julia</code> leveraging many JavaScript technologies for the browser. It has the feature of being reactive, making it well suited for many exploratory tasks and pedagogical demonstrations.</li>
<li><a href="https://www.julia-vscode.org/">Visual Studio Code</a>: <code>Julia</code> is a supported language for the Visual Studio Code editor of Microsoft, a programmer’s IDE.</li>
</ul>
<p>These notes use <code>quarto</code> to organize the mix of text, code, and graphics. The <code>quarto</code> publishing system is developed by <a href="https://posit.co/">Posit</a>, the developers of the wildly sucessful <code>RStudio</code> interface for <code>R</code>. The code snippets are run as blocks (within <code>IJulia</code>) and the last command executed is shown. (If code is copy-and-pasted into the REPL, each line’s output will be displayed.) The code display occurs below the cell, as here, where we show that <code>Julia</code> can handle basic addition:</p>
<div class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fl">2</span> <span class="op">+</span> <span class="fl">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-display" data-execution_count="2">
<pre><code>4</code></pre>
</div>
</div>
</section>
<section id="overview-of-some-basics" class="level2">
<h2 class="anchored" data-anchor-id="overview-of-some-basics">Overview of some basics</h2>
<p>This section gives a quick orientation for using <code>Julia</code>. See this compiled collection of <a href="https://julialang.org/learning/tutorials/">tutorials</a> for more comprehensive introductions.</p>
<p>As will be seen, <code>Julia</code> use <em>multiple dispatch</em> (as does <code>R</code>) where different function methods can be called using the same generic name. Different methods are dispatched depending on the type and number of the arguments. The <code>+</code> sign above, is actually a function call to the <code>+</code> function, which in base <code>Julia</code> has over 200 different methods, as there are many different implementations for addition. For a beginner this is great – fewer new function names to remember.</p>
<p><code>Julia</code> is a <em>dynamically typed</em> language, like <code>R</code> and <code>Python</code>, meaning variables can be reassigned to different values and with different types.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Dynamicness makes interactive usage at the REPL or through a notebook much easier.</p>
<p>Julia supports the usual mathematical operations familiar to users of a calculator, such as <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, and <code>^</code>. In addition, there a numerous built in functions such as mathematical ones like <code>sqrt</code> or programming oriented ones, like <code>map</code>.</p>
<p>These functions are called with arguments which may be <em>positional</em> (<span class="math inline">\(0\)</span>, <span class="math inline">\(1,\)</span> or more positional arguments) or specified by <em>keywords</em>. Multiple dispatch considers the positions and types of arguments a function is called with.</p>
<div class="callout-note callout callout-style-default callout-captioned">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-caption-container flex-fill">
Interactive help
</div>
</div>
<div class="callout-body-container callout-body">
<p>Interacting with <code>Julia</code> primarily involves variables and functions. Most all functions have documentation, which can be called up by prefacing the function name with an immediate question mark, as in <code>?sqrt</code> to see the documentation for <code>sqrt</code>. More than one method may be documented. A call like <code>?sqrt(9)</code> will limit the help to the method called by <code>sqrt(9)</code> (the square root function for integers.)</p>
</div>
</div>
<p>Values in <code>Julia</code> have types. A particular instance will have a concrete type but <em>abstract</em> types help to organize code bases and participate in dispatch. Values can be assigned to variable names, or bindings. The ability to simply create new user-defined types makes generic programming quite accessible and <code>Julia</code> code very <em>composable</em>.</p>
<p>This simple example, taking the average of several numbers, shows most of this:</p>
<div class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>xs <span class="op">=</span> [<span class="fl">1</span>, <span class="fl">2</span>, <span class="fl">3</span>, <span class="fl">7</span>, <span class="fl">9</span>]</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="fu">sum</span>(xs) <span class="op">/</span> <span class="fu">length</span>(xs)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>4.4</code></pre>
</div>
</div>
<p>The first line <em>assigns</em> to a variable, <code>xs</code>, a value that is a <em>vector</em> of numbers, integers of type <code>Int64</code> in this case. For this illustration, a vector is a container of different numbers. The second line calls three functions: <code>sum</code> to add the elements in the vector; <code>length</code> to count the number of elements in the vector; and <code>/</code> to divide these two quantities. All of these functions are <em>generic</em>, with different methods for different types of argument(s). The same pattern would work for different container types, such as a tuple:</p>
<div class="cell" data-execution_count="3">
<div class="sourceCode cell-code" id="cb5"><pre class="sourceCode julia code-with-copy"><code class="sourceCode julia"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>xs <span class="op">=</span> (<span class="fl">1</span>, <span class="fl">2</span>, <span class="fl">3</span>, <span class="fl">7</span>, <span class="fl">9</span>) <span class="co"># tuple</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">sum</span>(xs) <span class="op">/</span> <span class="fu">length</span>(xs)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>4.4</code></pre>
</div>
</div>
<p>The takeaway – we can focus more on what the computations mean, and less on how to program a particular computation.</p>
</section>
<section id="add-on-packages" class="level2">
<h2 class="anchored" data-anchor-id="add-on-packages">Add-on packages</h2>
<p>Base <code>Julia</code> provides a very useful programming environment which can be extended through <em>packages</em>. Some packages are provided by base <code>Julia</code>, such as <code>Dates</code>, others are external add-on packages, such as <code>IJulia</code>, mentioned previously. Julia has one key package, <code>Pkg</code>, to manage the installation. By default, the installation of a single package will download all dependent packages. On installation, packages are partially compiled. This speeds up the <em>loading</em> of a package when it is used within a session, but can slow down package installation.</p>
<p>Packages need be installed just once, but must be loaded each session. Loading a package is done by a command like <code>using Statistics</code>, which will load the built in <code>Statistics</code> package. At the REPL, calling <code>using PKGNAME</code> on an uninstalled package will lead to a prompt to install the package. For other interfaces, packages may need to be installed through the <code>Pkg</code> package, loaded through <code>using Pkg</code>.</p>
<p>When a package is loaded its exported functions are made available to use directly. Non-exported functions can be accessed by <em>qualifying</em> the function with the name of a <em>module</em> (conventionally the name of the package). For example, we will see the command <code>CSV.read</code> which calls the <code>read</code> function provided in the <code>CSV</code> package which has a <code>CSV</code> module.</p>
<p>Most packages are designed to <em>extend</em> generic functions that may be defined elsewhere. Not all. When there are conflicts, they can be resolved by either just <em>importing</em> the packages and qualifying all uses, or qualifying the uses that conflict.</p>
<p>These notes will utilize numerous add-on packages including:</p>
<ul>
<li><p><a href="https://github.com/JuliaStats/StatsBase.jl"><code>StatsBase</code></a>, to extend the built-in <code>Statistics</code> package;</p></li>
<li><p><a href="https://github.com/JuliaPlots/StatsPlots.jl"><code>StatsPlots</code></a>, for easy-to-make statistical plots, which display on a variety of graphing backends;</p></li>
<li><p><a href="https://github.com/MakieOrg/AlgebraOfGraphics.jl"><code>AlgebraOfGraphics</code></a> and <a href="https://github.com/MakieOrg/AlgebraOfGraphics.jl"><code>CairoMakie</code></a>, for more advanced statistical graphics;</p></li>
<li><p><a href="https://github.com/JuliaData/CSV.jl"><code>CSV</code></a> and <a href="https://github.com/JuliaData/DataFrames.jl"><code>DataFrames</code></a> for working with tabular data;</p></li>
<li><p><a href="https://github.com/JuliaStats/RDatasets.jl"><code>RDatasets</code></a>, for some handy datasets;</p></li>
<li><p><a href="https://github.com/nalimilan/FreqTables.jl"><code>FreqTables</code></a> and <a href="https://github.com/JuliaData/CategoricalArrays.jl"><code>CategoricalArrays</code></a>, for some needed functionality;</p></li>
<li><p><a href="https://github.com/JuliaStats/Distributions.jl"><code>Distributions</code></a>, for probability distributions;</p></li>
<li><p><a href="https://github.com/JuliaStats/HypothesisTests.jl"><code>HypothesisTests</code></a>, for the computation of significance tests and confidence intervals; and</p></li>
<li><p><a href="https://github.com/JuliaStats/GLM.jl"><code>GLM</code></a>, <a href="https://github.com/JuliaStats/Loess.jl"><code>Loess</code></a>, and <a href="https://github.com/getzze/RobustModels.jl"><code>RobustModels</code></a>, for statistical modeling.</p></li>
</ul>
<p>Most of these are maintained by the <code>StatsBase</code> organization, which provides the <code>StatsKit</code> package to load all these with a single command, though we don’t illustrate that.</p>
<hr>
<p>Copyright 2023, John Verzani. All rights reserved.</p>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-Embrace-Uncertainty-Fitting-Mixed-Effects-Models-with-Julia" class="csl-entry" role="doc-biblioentry">
Alday, P., Kliegl, R., and Bates, D. (2022), <em>Embrace uncertainty: Fitting mixed-effects models with julia</em>, https://juliamixedmodels.github.io/EmbraceUncertainty/.
</div>
<div id="ref-bezanson2017julia" class="csl-entry" role="doc-biblioentry">
Bezanson, J., Edelman, A., Karpinski, S., and Shah, V. B. (2017), <span>“<a href="https://doi.org/10.1137/141000671">Julia: A fresh approach to numerical computing</a>,”</span> <em>SIAM review</em>, SIAM, 59, 65–98.
</div>
<div id="ref-JuliaForDataAnalysis" class="csl-entry" role="doc-biblioentry">
Kamiński, B. (2022), <em><a href="https://www.manning.com/books/julia-for-data-analysis">Julia for data analysis</a></em>, Manning.
</div>
<div id="ref-nazarathy2021statisticsjulia" class="csl-entry" role="doc-biblioentry">
Nazarathy, Y., and Klok, H. (2021), <em>Statistics with julia: Fundamentals for data science, machine learning and artificial intelligence</em>, Springer.
</div>
<div id="ref-storopolihuijzeralonso2021juliadatascience" class="csl-entry" role="doc-biblioentry">
Storopoli, J., Huijzer, R., and Alonso, L. (2021), <em><a href="https://juliadatascience.io">Julia data science</a></em>.
</div>
</div>
</section>
</section>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr>
<ol>
<li id="fn1"><p>With the one caveat that generic function names can not be reassigned as variables or vice versa.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</main>
<!-- /main column -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const toggleBodyColorMode = (bsSheetEl) => {
const mode = bsSheetEl.getAttribute("data-mode");
const bodyEl = window.document.querySelector("body");
if (mode === "dark") {
bodyEl.classList.add("quarto-dark");
bodyEl.classList.remove("quarto-light");
} else {
bodyEl.classList.add("quarto-light");
bodyEl.classList.remove("quarto-dark");
}
}
const toggleBodyColorPrimary = () => {
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
if (bsSheetEl) {
toggleBodyColorMode(bsSheetEl);
}
}
toggleBodyColorPrimary();
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const clipboard = new window.ClipboardJS('.code-copy-button', {
target: function(trigger) {
return trigger.previousElementSibling;
}
});
clipboard.on('success', 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();
});
function tippyHover(el, contentFn) {
const config = {
allowHTML: true,
content: contentFn,
maxWidth: 500,
delay: 100,
arrow: false,
appendTo: function(el) {
return el.parentElement;
},
interactive: true,
interactiveBorder: 10,
theme: 'quarto',
placement: 'bottom-start'
};
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);
return note.innerHTML;
});
}
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;
});
}
}
var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
var filterRegex = new RegExp('/' + window.location.host + '/');
var isInternal = (href) => {
return filterRegex.test(href) || localhostRegex.test(href);
}
// Inspect non-navigation links and adorn them if external
var links = window.document.querySelectorAll('a: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)');
for (var i=0; i<links.length; i++) {
const link = links[i];
if (!isInternal(link.href)) {
// target, if specified
link.setAttribute("target", "_blank");
}
}
});
</script>
</div> <!-- /content -->
</body></html>