From fae50809c9b01582918fefa5e03f92227a461d99 Mon Sep 17 00:00:00 2001 From: John Benninghoff Date: Wed, 4 Sep 2024 15:24:02 -0500 Subject: [PATCH] build_quarto_site(unfreeze = FALSE) for release 1.2.8 --- .../r-books/execute-results/html.json | 4 +- _freeze/site_libs/quarto-listing/list.min.js | 2 +- docs/LICENSE.html | 49 +- docs/NEWS.html | 58 +- docs/TODO.html | 49 +- docs/analysis/FaultTree.html | 51 +- docs/analysis/advanced-r-1.html | 51 +- docs/analysis/advanced-r-2.html | 53 +- docs/analysis/advanced-r-3.html | 51 +- docs/analysis/advanced-r-4.html | 53 +- docs/analysis/cond-prob.html | 53 +- docs/analysis/ggplot2-1.html | 53 +- docs/analysis/ggplot2-2.html | 51 +- docs/analysis/ggplot2-3.html | 51 +- docs/analysis/ggplot2-4.html | 51 +- docs/analysis/ggplot2-5.html | 51 +- docs/analysis/hockey-cards.html | 51 +- docs/analysis/r-books.html | 113 ++- docs/analysis/r-setup-log.html | 51 +- docs/analysis/r-training-log.html | 51 +- docs/analysis/using-Rcpp.html | 51 +- docs/changelog.html | 58 +- docs/index.html | 51 +- docs/index.xml | 662 +++++++++++++++++- docs/search.json | 29 +- .../bootstrap/bootstrap-dark.min.css | 4 +- docs/site_libs/bootstrap/bootstrap.min.css | 4 +- .../quarto-syntax-highlighting.css | 2 + docs/site_libs/quarto-html/quarto.js | 15 +- docs/site_libs/quarto-listing/list.min.js | 2 +- docs/site_libs/quarto-nav/quarto-nav.js | 36 + docs/site_libs/quarto-search/quarto-search.js | 6 +- docs/sitemap.xml | 4 +- 33 files changed, 1465 insertions(+), 456 deletions(-) diff --git a/_freeze/analysis/r-books/execute-results/html.json b/_freeze/analysis/r-books/execute-results/html.json index d3e3be87..d87e11b1 100644 --- a/_freeze/analysis/r-books/execute-results/html.json +++ b/_freeze/analysis/r-books/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "6accab22342808f24ca539b9fd8bea9d", + "hash": "e93ce27fcd4e48c1d55eb43099513ce9", "result": { "engine": "knitr", - "markdown": "---\ntitle: \"R Books\"\nauthor: \"John Benninghoff\"\ndate: '2023-11-17'\ndate-modified: '2024-01-01'\ncategories: reading\norder: 1\noutput:\n html_notebook:\n theme:\n version: 5\n preset: bootstrap\n css: assets/extra.css\n pandoc_args: --shift-heading-level-by=1\n toc: yes\n toc_float:\n collapsed: no\n smooth_scroll: no\n---\n\n\nAn actively maintained and curated list of R Books and other recommended resources from my reading list.\n\n# Libraries\n\nLibraries used in this notebook.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\nlibrary(ggplot2)\nlibrary(ggthemes)\nlibrary(cranlogs)\nlibrary(dplyr)\n```\n:::\n\n\n# Getting Started\n\nBooks and resources I recommend for learning R.\n\n## R for Data Science\n\n[R for Data Science (2e)](https://r4ds.hadley.nz) - Second Edition of\n[Hadley Wickham's](https://hadley.nz/) introductory book on R and exploratory data analysis. The\nbook contains example code and exercises in most chapters. I used the\n[first edition](https://r4ds.had.co.nz/) as my primary source when I was first learning R, and\nstill recommend the book for beginners who want to learn R. The book teaches the basics of using\ntidyverse R^[For a detailed explanation of \"tidyverse R\", see [R Dialects]] for exploratory data\nanalysis and visualization. A companion book provides suggested\n[solutions](https://mine-cetinkaya-rundel.github.io/r4ds-solutions/) to the exercises.\n\nSample visualization from the first chapter:\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# visualization from https://r4ds.hadley.nz/data-visualize#first-steps\nggplot(\n data = penguins,\n mapping = aes(x = flipper_length_mm, y = body_mass_g)\n) +\n geom_point(aes(color = species, shape = species)) +\n geom_smooth(method = \"lm\") +\n labs(\n title = \"Body mass and flipper length\",\n subtitle = \"Dimensions for Adelie, Chinstrap, and Gentoo Penguins\",\n x = \"Flipper length (mm)\", y = \"Body mass (g)\",\n color = \"Species\", shape = \"Species\"\n ) +\n scale_color_colorblind()\n```\n\n::: {.cell-output-display}\n![](r-books_files/figure-html/r4ds-1.png){width=816}\n:::\n:::\n\n\n## Resources\n\nIn addition to R for Data Science, I recommend the following resources for new R users:\n\n- [The R Graph Gallery](https://r-graph-gallery.com/) - library of charts made with R and ggplot2\n- Packages for writing better code:\n - [renv](https://rstudio.github.io/renv/) - for package version management by project\n - [styler](https://styler.r-lib.org/) - for consistent formatting of R code\n - [lintr](https://lintr.r-lib.org) - for avoiding common mistakes\n- Style guides for writing better code:\n - [tidyverse style guide](https://style.tidyverse.org/) - implemented by styler\n - [Google's R Style Guide](https://google.github.io/styleguide/Rguide.html) - a fork of the\n tidyverse guide\n\n[rdev](https://jabenninghoff.github.io/rdev/index.html), my personalized collection of R development\ntools, includes all three of these packages and more, along with my own\n[style guide](https://jabenninghoff.github.io/rdev/articles/style-guide.html) and R environment\nsetup [instructions](https://jabenninghoff.github.io/rdev/articles/rdev.html).\n\n# Additional Reading\n\nBooks I read to improve my knowledge of R.\n\n- [R Packages (2e)](https://r-pkgs.org/) - the second edition of Hadley Wickham's book on writing R\n packages, which I used to build [rdev](https://github.com/jabenninghoff/rdev)\n- [Advanced R](https://adv-r.hadley.nz/) - the second edition of Hadley's book on R programming,\n which explains the R language (the [first edition](http://adv-r.had.co.nz) uses more base R than\n the second edition)\n- [Advanced R Solutions](https://advanced-r-solutions.rbind.io) - solutions to exercises from\n *Advanced R*\n- [ggplot2: Elegant Graphics for Data Analysis (3e)](https://ggplot2-book.org) - the third edition\n of Hadley's book on his implementation of Leland Wilkinson's *Grammar of Graphics*\n- [Solutions to ggplot2: Elegant Graphics for Data Analysis](https://ggplot2-book-solutions-3ed.netlify.app) -\n solutions to exercises from *ggplot2*\n\nMy own notes and solutions to the Advanced R and ggplot2 exercises are available on this site.\n\n## raps-with-r\n\n[Building reproducible analytical pipelines with R](https://raps-with-r.dev) - the stated goal of\nthe book is to improve the reproducibility of data analysis. I don't recommend this book. Section 1\nis a reasonably good introduction to git and GitHub, but introduces trunk-based development without\ncovering linear commit history. Section 2 provides some good advice, but much that I disagree with,\nincluding inline use of `knitr::knit_child` to automate creation of sections (which break the\nnotebook workflow) and `fusen` to create packages from `.Rmd` files, which I found to create extra\nwork with no clear benefits over using and/or extending the standard package layout like\n[vertical](https://www.crumplab.com/vertical/index.html) or my own\n[layout](https://jabenninghoff.github.io/rdev/articles/analysis-package-layout.html) from\n[rdev](https://jabenninghoff.github.io/rdev/index.html). (Interestingly, the author of vertical is\n[also](https://www.crumplab.com/blog/post_886_10_14_22_quartoProjects/)\n[switching](https://www.crumplab.com/blog/663_quarto_projects/) to [Quarto](https://quarto.org) for\nreproducible research and analysis) I also found the code examples to be inconsistent and a bit\nclunky.\n\nChapter 12 gives recommendations on testing: unit testing with some basic examples,\n[assertive programming](https://en.wikipedia.org/wiki/Assertion_(software_development)),\n[Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development), and test\ncoverage. It suggests three packages for R assertions:\n[`assertthat`](https://github.com/hadley/assertthat),\n[`chk`](https://poissonconsulting.github.io/chk/), and\n[`checkmate`](https://mllg.github.io/checkmate/). Both `chk` and `checkmate` are designed to check\nfunction arguments; of the two, `checkmate` appears to be more robust and built to address the\ndownside of R being a dynamically typed language.\n\nFor data validation, I currently use `stopifnot()`, although I may switch to either `assertr` or\n`validate`, which are both popular packages. I validate function arguments using manual checks, but\n`checkmate` looks appealing as a way to write more succinct code. Total downloads for the `assertr`,\n`validate`, `chk`, and `checkmate` packages for the last month are listed below:\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncran_downloads(\n packages = c(\"assertr\", \"validate\", \"chk\", \"checkmate\"),\n when = \"last-month\"\n) |>\n group_by(package) |>\n summarize(downloads = sum(count), as_of = max(date))\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 4 × 3\n package downloads as_of \n \n1 assertr 1730 2024-06-04\n2 checkmate 246000 2024-06-04\n3 chk 12787 2024-06-04\n4 validate 1926 2024-06-04\n```\n\n\n:::\n:::\n\n\n2023-12-29 Update: I've started using `checkmate` to check function arguments and have found\nthat `validate` is better overall at data validation.\n\nChapter 13 introduces [targets](https://docs.ropensci.org/targets/), \"a Make-like pipeline tool for\nstatistics and data science in R.\" Conceptually, targets is very similar to an R Notebook, but like\nMake, will skip components that are up to date, and can run targets in parallel to speed up builds.\ntargets can also render R Markdown documents using the `tarchetypes` package. I found the example\ntarget pipeline in the book convoluted and didn't attempt to follow it. The targets\n[manual](https://books.ropensci.org/targets/) explains that it implements\n[two kinds](https://books.ropensci.org/targets/literate-programming.html#scope) of literate\nprogramming:\n\n> 1. A literate programming source document (or Quarto project) that renders inside an individual\n> target. Here, you define a special kind of target that runs a lightweight R Markdown report\n> which depends on upstream targets.\n> 1. Target Markdown, an overarching system in which one or more Quarto or R Markdown files write\n> the _targets.R file and encapsulate the pipeline.\n\nOf these two types, the second is a better fit with my preferred workflow: including multiple\nself-contained notebooks in a single repository. From the\n[appendix](https://books.ropensci.org/targets/markdown.html), the design of Target Markdown supports\nboth interactive development using notebooks and running a pipeline non-interactively when rendering\nthe final document. For my work, targets doesn't offer significant advantages over using R\nMarkdown and Quarto - the only slowdown I typically encounter is when building a site with many\nnotebooks, which the Quarto [freeze](https://quarto.org/docs/projects/code-execution.html#freeze)\noption handles by only re-rendering documents when the source file changes. (I'm not performing the\nlarge, complex computations that targets is designed for)\n\nChapter 14 covers Docker, and asserts that it is necessary for reproducibility. While using Docker\nensures a stable operating system environment, I think the book overstates the case for\nreproducibility, citing a single example where the operating system changed the results of an\nanalysis because the scripts relied on OS file ordering. Much like use of targets, Docker would be\nmost useful for projects with complex development environments shared across teams, but much of the\nbenefits can be achieved using other approaches, like using [OS-independent](https://fs.r-lib.org)\ncode. The chapter also encourages using a \"frozen\" development environment that is updated on a\nfixed schedule to minimize the impact of frequent updates. This is exactly the opposite of the\nmodern DevOps approach - the issues created by small, frequent updates are smaller and easier to\naddress than the more complex problems created by large upgrades. I *always* start development by\nupdating packages to the latest production release - while this sometimes introduces issues, they\nare typically easy to fix, and prioritizing maintenance first improves quality and security.\n\nAn alternate approach to using Docker is to leverage\n[GitHub Actions](https://github.com/features/actions), which provides on-demand virtual machines\nthat can be used to consistently test, build, and deploy code. The Tidyverse community provides a\n[library](https://github.com/r-lib/actions) of GitHub Actions for R, which I've customized for\n[rdev](https://jabenninghoff.github.io/rdev/reference/use_rdev_package.html). In fact, chapter 15\ncovers use of GitHub Actions using r-lib and presents them as a potential alternative for Docker.\n\nOverall, I do follow the book's core recommendations for reproducibility:\n\n- Use version control extensively\n- Use trunk-based development\n- Adopt functional programming and [DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)\n- Use R Markdown which embeds analysis code and code output directly into the written report\n- Use [renv](https://rstudio.github.io/renv/) to manage dependencies\n- Package all R code and publish using GitHub Pages\n- Write unit tests using [testthat](https://testthat.r-lib.org)\n- Use assertions to validate function arguments and imported data\n- Check test coverage using [`covr`](https://covr.r-lib.org)\n- Use automated builds (but using Quarto instead of targets)\n\nI would consider use of targets and Docker for larger, more complex, or long-lived projects, but I\nfound that `fusen` offered no clear benefits and wouldn't recommend its use. I think the biggest\nlesson I took from the book was to follow DRY a bit more strictly than I currently do, and use more\nfunctions, tests, and assertions in my analysis code.\n\nThe book does reference some interesting reading I've added to my list:\n\n- John M. Chambers. \"Object-Oriented Programming, Functional Programming and R.\"\n Statist. Sci. 29 (2) 167 - 180, May 2014. \n- [Trunk-Based Development And Branch By Abstraction](https://trunkbaseddevelopment.com/)\n\nWhile reading the book, I discovered some interesting additional resources:\n\n- [Vertical](https://www.crumplab.com/vertical/), a \"an R-based structured workflow for creating\n and sharing research assets in the form of an extended R package\", which I plan to review and\n compare to [rdev](https://jabenninghoff.github.io/rdev/)\n- [Four ways to write assertion checks in R](https://blog.djnavarro.net/posts/2023-08-08_being-assertive/) -\n an article on four methods for writing assertions in R:\n - Use `stopifnot()` from base R\n - Use the [`assertthat`](https://github.com/hadley/assertthat) package (last updated March 2019)\n - Use the [`assertive`](https://bitbucket.org/richierocks/assertive/src/master/) package\n (last updated July 2020)\n - Use the [`assertr`](https://docs.ropensci.org/assertr/) package for data assertions, which\n works especially well for assertion checks against data frames used in data analysis\n- I also revisited the [`validate`](https://github.com/data-cleaning/validate) package, a data\n validation rules engine, which includes the Data Validation Cookbook (in [Future Reading])\n\n# Future Reading\n\nR books on my reading list.\n\n- [The R Manuals](https://rstudio.github.io/r-manuals/) - a re-styled version of the original R\n manuals, published using Quarto (starting with *Writing R Extensions*)\n- [R Markdown: The Definitive Guide](https://bookdown.org/yihui/rmarkdown/) - written by the author\n of [knitr](https://yihui.org/knitr/)\n- [R Markdown Cookbook](https://bookdown.org/yihui/rmarkdown-cookbook/) - the follow-up to *The\n Definitive Guide*\n- [The Data Validation Cookbook](https://data-cleaning.github.io/validate/) - a book on the R\n [validate](https://CRAN.R-project.org/package=validate) package\n- [Discovering Statistics Using R](https://us.sagepub.com/en-us/nam/discovering-statistics-using-r/book236067) - recommended to me\n as an introduction to statistics using R\n\n# R Dialects\n\nAn explanatory note on the R dialects of base R and tidyverse R.\n\nThe [R programming language](https://en.wikipedia.org/wiki/R_(programming_language)) is over 30\nyears old and has a large number of [packages](https://en.wikipedia.org/wiki/R_package) (R\nlibraries) that extend R. Unlike\n[python](https://en.wikipedia.org/wiki/Python_(programming_language)) (a general purpose language),\nR was designed specifically for analysis, visualization, and statistical modeling, which is why I\n[chose R](https://www.information-safety.org/2020/09/11/working-with-r/) for data analysis: it has\nbuilt-in support for data structures like data frames (implemented in python using\n[pandas](https://en.wikipedia.org/wiki/Pandas_(software))), vectors, packages for just about any\nstatistical tool you'd need, and of course, [ggplot2](https://en.wikipedia.org/wiki/Ggplot2). In\nfairness, python is more popular, more robust, and a better tool for some tasks, like data\nacquisition and machine learning (which were not priorities for my use).\n\nLike many human languages, R has developed two distinct dialects: base R and tidyverse R. Base R\nconsists of the [packages](https://cran.r-project.org/doc/FAQ/R-FAQ.html#Add_002don-packages-in-R)\nincluded in the R distribution\n*(base, compiler, datasets, graphics, grDevices, grid, methods, parallel, splines, stats, stats4, tcltk, tools, utils)*, and the\n[Tidyverse](https://en.wikipedia.org/wiki/Tidyverse) is a collection of packages that implement a\n[domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language) for data\nanalysis, originally created by [Hadley Wickham](https://en.wikipedia.org/wiki/Hadley_Wickham).\n\nIn my experience, tidyverse R is better for data analysis, where base R is better for writing\npackages - tidyverse functions are closer to natural language, but have many more dependencies.\n[Comparing](https://atrebas.github.io/post/2019-03-03-datatable-dplyr/) two popular tools for data\nmanipulation, [dplyr](https://dplyr.tidyverse.org) (tidyverse R) and\n[data.table](https://rdatatable.gitlab.io/data.table/) (base R) shows these differences.\n\nThis code snippet is from a short analysis of survey responses using dplyr:\n\n```r\nsurvey_results <- survey_import |>\n mutate(across(Q1:Q7, ~ case_when(\n .x == \"strongly disagree\" ~ 1,\n .x == \"disagree\" ~ 2,\n .x == \"neither agree nor disagree\" ~ 3,\n .x == \"agree\" ~ 4,\n .x == \"strongly agree\" ~ 5\n ))) |>\n mutate(Q8 = as.numeric(Q8 == \"Yes\")) |>\n arrange(end_date)\n```\n\nThe code is reasonably easy to understand, even if you're not familiar with R.\n\nThe same code written in data.table isn't as clear:\n\n```r\nlikert_5 <- c(\n \"strongly disagree\", \"disagree\", \"neither agree nor disagree\",\n \"agree\", \"strongly agree\"\n)\nq_likert <- paste0(\"Q\", 1:7)\nq_yesno <- \"Q8\"\n\nsurvey_results <- copy(survey_import)\nsurvey_results <- survey_results[\n , (q_likert) := lapply(.SD, \\(x) as.numeric(factor(x, levels = likert_5))),\n .SDcols = q_likert\n][\n , (q_yesno) := lapply(.SD, \\(x) as.numeric(x == \"Yes\")),\n .SDcols = q_yesno\n][\n order(end_date)\n]\n```\n\nWhile it may be harder to read, data.table has some clear advantages: it is quite\n[fast](https://h2oai.github.io/db-benchmark/), especially with very large datasets, and has no\n[dependencies](https://github.com/Rdatatable/data.table/blob/master/DESCRIPTION) other than base R,\nwhere dplyr has many.\n\nThese tradeoffs are why I tend to use tidyverse R for analysis and base R for functions (most\ntidyverse expressions have functional equivalents in base R). Code used in data analysis should be\nclear and easy to read, which tidyverse R excels at. Packaged functions provide documentation and\nthe source code isn't typically read, but many dependencies can be problematic; `R CMD check` will\nraise a NOTE if there are too many imports.\n", + "markdown": "---\ntitle: \"R Books\"\nauthor: \"John Benninghoff\"\ndate: '2023-11-17'\ndate-modified: '2024-01-01'\ncategories: reading\norder: 1\noutput:\n html_notebook:\n theme:\n version: 5\n preset: bootstrap\n css: assets/extra.css\n pandoc_args: --shift-heading-level-by=1\n toc: yes\n toc_float:\n collapsed: no\n smooth_scroll: no\n---\n\n\n\n\nAn actively maintained and curated list of R Books and other recommended resources from my reading list.\n\n# Libraries\n\nLibraries used in this notebook.\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\nlibrary(ggplot2)\nlibrary(ggthemes)\nlibrary(cranlogs)\nlibrary(dplyr)\n```\n:::\n\n\n\n\n# Getting Started\n\nBooks and resources I recommend for learning R.\n\n## R for Data Science\n\n[R for Data Science (2e)](https://r4ds.hadley.nz) - Second Edition of\n[Hadley Wickham's](https://hadley.nz/) introductory book on R and exploratory data analysis. The\nbook contains example code and exercises in most chapters. I used the\n[first edition](https://r4ds.had.co.nz/) as my primary source when I was first learning R, and\nstill recommend the book for beginners who want to learn R. The book teaches the basics of using\ntidyverse R^[For a detailed explanation of \"tidyverse R\", see [R Dialects]] for exploratory data\nanalysis and visualization. A companion book provides suggested\n[solutions](https://mine-cetinkaya-rundel.github.io/r4ds-solutions/) to the exercises.\n\nSample visualization from the first chapter:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# visualization from https://r4ds.hadley.nz/data-visualize#first-steps\nggplot(\n data = penguins,\n mapping = aes(x = flipper_length_mm, y = body_mass_g)\n) +\n geom_point(aes(color = species, shape = species)) +\n geom_smooth(method = \"lm\") +\n labs(\n title = \"Body mass and flipper length\",\n subtitle = \"Dimensions for Adelie, Chinstrap, and Gentoo Penguins\",\n x = \"Flipper length (mm)\", y = \"Body mass (g)\",\n color = \"Species\", shape = \"Species\"\n ) +\n scale_color_colorblind()\n```\n\n::: {.cell-output-display}\n![](r-books_files/figure-html/r4ds-1.png){width=816}\n:::\n:::\n\n\n\n\n## Resources\n\nIn addition to R for Data Science, I recommend the following resources for new R users:\n\n- [The R Graph Gallery](https://r-graph-gallery.com/) - library of charts made with R and ggplot2\n- Packages for writing better code:\n - [renv](https://rstudio.github.io/renv/) - for package version management by project\n - [styler](https://styler.r-lib.org/) - for consistent formatting of R code\n - [lintr](https://lintr.r-lib.org) - for avoiding common mistakes\n- Style guides for writing better code:\n - [tidyverse style guide](https://style.tidyverse.org/) - implemented by styler\n - [Google's R Style Guide](https://google.github.io/styleguide/Rguide.html) - a fork of the\n tidyverse guide\n\n[rdev](https://jabenninghoff.github.io/rdev/index.html), my personalized collection of R development\ntools, includes all three of these packages and more, along with my own\n[style guide](https://jabenninghoff.github.io/rdev/articles/style-guide.html) and R environment\nsetup [instructions](https://jabenninghoff.github.io/rdev/articles/rdev.html).\n\n# Additional Reading\n\nBooks I read to improve my knowledge of R.\n\n- [R Packages (2e)](https://r-pkgs.org/) - the second edition of Hadley Wickham's book on writing R\n packages, which I used to build [rdev](https://github.com/jabenninghoff/rdev)\n- [Advanced R](https://adv-r.hadley.nz/) - the second edition of Hadley's book on R programming,\n which explains the R language (the [first edition](http://adv-r.had.co.nz) uses more base R than\n the second edition)\n- [Advanced R Solutions](https://advanced-r-solutions.rbind.io) - solutions to exercises from\n *Advanced R*\n- [ggplot2: Elegant Graphics for Data Analysis (3e)](https://ggplot2-book.org) - the third edition\n of Hadley's book on his implementation of Leland Wilkinson's *Grammar of Graphics*\n- [Solutions to ggplot2: Elegant Graphics for Data Analysis](https://ggplot2-book-solutions-3ed.netlify.app) -\n solutions to exercises from *ggplot2*\n\nMy own notes and solutions to the Advanced R and ggplot2 exercises are available on this site.\n\n## raps-with-r\n\n[Building reproducible analytical pipelines with R](https://raps-with-r.dev) - the stated goal of\nthe book is to improve the reproducibility of data analysis. I don't recommend this book. Section 1\nis a reasonably good introduction to git and GitHub, but introduces trunk-based development without\ncovering linear commit history. Section 2 provides some good advice, but much that I disagree with,\nincluding inline use of `knitr::knit_child` to automate creation of sections (which break the\nnotebook workflow) and `fusen` to create packages from `.Rmd` files, which I found to create extra\nwork with no clear benefits over using and/or extending the standard package layout like\n[vertical](https://www.crumplab.com/vertical/index.html) or my own\n[layout](https://jabenninghoff.github.io/rdev/articles/analysis-package-layout.html) from\n[rdev](https://jabenninghoff.github.io/rdev/index.html). (Interestingly, the author of vertical is\n[also](https://www.crumplab.com/blog/post_886_10_14_22_quartoProjects/)\n[switching](https://www.crumplab.com/blog/663_quarto_projects/) to [Quarto](https://quarto.org) for\nreproducible research and analysis) I also found the code examples to be inconsistent and a bit\nclunky.\n\nChapter 12 gives recommendations on testing: unit testing with some basic examples,\n[assertive programming](https://en.wikipedia.org/wiki/Assertion_(software_development)),\n[Test-Driven Development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development), and test\ncoverage. It suggests three packages for R assertions:\n[`assertthat`](https://github.com/hadley/assertthat),\n[`chk`](https://poissonconsulting.github.io/chk/), and\n[`checkmate`](https://mllg.github.io/checkmate/). Both `chk` and `checkmate` are designed to check\nfunction arguments; of the two, `checkmate` appears to be more robust and built to address the\ndownside of R being a dynamically typed language.\n\nFor data validation, I currently use `stopifnot()`, although I may switch to either `assertr` or\n`validate`, which are both popular packages. I validate function arguments using manual checks, but\n`checkmate` looks appealing as a way to write more succinct code. Total downloads for the `assertr`,\n`validate`, `chk`, and `checkmate` packages for the last month are listed below:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncran_downloads(\n packages = c(\"assertr\", \"validate\", \"chk\", \"checkmate\"),\n when = \"last-month\"\n) |>\n group_by(package) |>\n summarize(downloads = sum(count), as_of = max(date))\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 4 × 3\n package downloads as_of \n \n1 assertr 1576 2024-09-03\n2 checkmate 324633 2024-09-03\n3 chk 13394 2024-09-03\n4 validate 1845 2024-09-03\n```\n\n\n:::\n:::\n\n\n\n\n2023-12-29 Update: I've started using `checkmate` to check function arguments and have found\nthat `validate` is better overall at data validation.\n\nChapter 13 introduces [targets](https://docs.ropensci.org/targets/), \"a Make-like pipeline tool for\nstatistics and data science in R.\" Conceptually, targets is very similar to an R Notebook, but like\nMake, will skip components that are up to date, and can run targets in parallel to speed up builds.\ntargets can also render R Markdown documents using the `tarchetypes` package. I found the example\ntarget pipeline in the book convoluted and didn't attempt to follow it. The targets\n[manual](https://books.ropensci.org/targets/) explains that it implements\n[two kinds](https://books.ropensci.org/targets/literate-programming.html#scope) of literate\nprogramming:\n\n> 1. A literate programming source document (or Quarto project) that renders inside an individual\n> target. Here, you define a special kind of target that runs a lightweight R Markdown report\n> which depends on upstream targets.\n> 1. Target Markdown, an overarching system in which one or more Quarto or R Markdown files write\n> the _targets.R file and encapsulate the pipeline.\n\nOf these two types, the second is a better fit with my preferred workflow: including multiple\nself-contained notebooks in a single repository. From the\n[appendix](https://books.ropensci.org/targets/markdown.html), the design of Target Markdown supports\nboth interactive development using notebooks and running a pipeline non-interactively when rendering\nthe final document. For my work, targets doesn't offer significant advantages over using R\nMarkdown and Quarto - the only slowdown I typically encounter is when building a site with many\nnotebooks, which the Quarto [freeze](https://quarto.org/docs/projects/code-execution.html#freeze)\noption handles by only re-rendering documents when the source file changes. (I'm not performing the\nlarge, complex computations that targets is designed for)\n\nChapter 14 covers Docker, and asserts that it is necessary for reproducibility. While using Docker\nensures a stable operating system environment, I think the book overstates the case for\nreproducibility, citing a single example where the operating system changed the results of an\nanalysis because the scripts relied on OS file ordering. Much like use of targets, Docker would be\nmost useful for projects with complex development environments shared across teams, but much of the\nbenefits can be achieved using other approaches, like using [OS-independent](https://fs.r-lib.org)\ncode. The chapter also encourages using a \"frozen\" development environment that is updated on a\nfixed schedule to minimize the impact of frequent updates. This is exactly the opposite of the\nmodern DevOps approach - the issues created by small, frequent updates are smaller and easier to\naddress than the more complex problems created by large upgrades. I *always* start development by\nupdating packages to the latest production release - while this sometimes introduces issues, they\nare typically easy to fix, and prioritizing maintenance first improves quality and security.\n\nAn alternate approach to using Docker is to leverage\n[GitHub Actions](https://github.com/features/actions), which provides on-demand virtual machines\nthat can be used to consistently test, build, and deploy code. The Tidyverse community provides a\n[library](https://github.com/r-lib/actions) of GitHub Actions for R, which I've customized for\n[rdev](https://jabenninghoff.github.io/rdev/reference/use_rdev_package.html). In fact, chapter 15\ncovers use of GitHub Actions using r-lib and presents them as a potential alternative for Docker.\n\nOverall, I do follow the book's core recommendations for reproducibility:\n\n- Use version control extensively\n- Use trunk-based development\n- Adopt functional programming and [DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself)\n- Use R Markdown which embeds analysis code and code output directly into the written report\n- Use [renv](https://rstudio.github.io/renv/) to manage dependencies\n- Package all R code and publish using GitHub Pages\n- Write unit tests using [testthat](https://testthat.r-lib.org)\n- Use assertions to validate function arguments and imported data\n- Check test coverage using [`covr`](https://covr.r-lib.org)\n- Use automated builds (but using Quarto instead of targets)\n\nI would consider use of targets and Docker for larger, more complex, or long-lived projects, but I\nfound that `fusen` offered no clear benefits and wouldn't recommend its use. I think the biggest\nlesson I took from the book was to follow DRY a bit more strictly than I currently do, and use more\nfunctions, tests, and assertions in my analysis code.\n\nThe book does reference some interesting reading I've added to my list:\n\n- John M. Chambers. \"Object-Oriented Programming, Functional Programming and R.\"\n Statist. Sci. 29 (2) 167 - 180, May 2014. \n- [Trunk-Based Development And Branch By Abstraction](https://trunkbaseddevelopment.com/)\n\nWhile reading the book, I discovered some interesting additional resources:\n\n- [Vertical](https://www.crumplab.com/vertical/), a \"an R-based structured workflow for creating\n and sharing research assets in the form of an extended R package\", which I plan to review and\n compare to [rdev](https://jabenninghoff.github.io/rdev/)\n- [Four ways to write assertion checks in R](https://blog.djnavarro.net/posts/2023-08-08_being-assertive/) -\n an article on four methods for writing assertions in R:\n - Use `stopifnot()` from base R\n - Use the [`assertthat`](https://github.com/hadley/assertthat) package (last updated March 2019)\n - Use the [`assertive`](https://bitbucket.org/richierocks/assertive/src/master/) package\n (last updated July 2020)\n - Use the [`assertr`](https://docs.ropensci.org/assertr/) package for data assertions, which\n works especially well for assertion checks against data frames used in data analysis\n- I also revisited the [`validate`](https://github.com/data-cleaning/validate) package, a data\n validation rules engine, which includes the Data Validation Cookbook (in [Future Reading])\n\n## rstats.wtf\n\n[What They Forgot to Teach You About R](https://rstats.wtf) - a book based on a workshop taught by\ncurrent and former posit employees intended for self-taught data analysts. It's short, still in\ndraft, and offers good advice on R development (I use *almost* all the suggestions):\n\n- Use an IDE (RStudio)\n- Don't save `.RData`\n- Restart R frequently\n- Automate long workflows using [targets](https://docs.ropensci.org/targets/)\n- Don't use `setwd()`\n- Use RStudio projects\n- Use [here](https://here.r-lib.org) and [fs](https://fs.r-lib.org) for paths\n- Use \"-\" as space and \"_\" as a field delimiter in\n [file names](https://speakerdeck.com/jennybc/how-to-name-files)\n- Use ISO standard dates (ISO 8601, YYYY-MM-DD)\n- Use version control (git, GitHub)\n- Use [renv](https://rstudio.github.io/renv/index.html), [rig](https://github.com/r-lib/rig/), and\n [homebrew](https://brew.sh)\n- Use `.Renviron` and `.Rprofile`\n- Use CRAN R and CRAN binaries to speed up package installation\n- Don't use Conda (for Python)\n- Update packages!\n- Use [debugging](https://rstats.wtf/debugging-r) commands and RStudio for troubleshooting\n- Search for error messages and read the source code to understand your problem\n\nThe book also suggests use of the [Posit Public Package Manager](https://p3m.dev/) (P3M). I'd *like*\nto agree with this advice, however, I've had problems with their binaries; this package (rtraining)\ndoesn't work when using P3M, and works fine with CRAN binary packages.\n\n## do4ds\n\n[DevOps for Data Science](https://do4ds.com), another book written by a Posit employee was brought\nto my attention thanks to a LinkedIn Post by [\\@Corey Neskey](https://www.linkedin.com/in/cneskey/)\n(It included a reference to rstats.wtf, which I read first). The book is split into 3 sections:\n\n1. [DevOps Lessons for Data Science](https://do4ds.com/chapters/sec1/1-0-sec-intro.html)\n (Chapters 1-6)\n1. [IT/Admin for Data Science](https://do4ds.com/chapters/sec2/2-0-sec-intro.html) (Chapters 7-14)\n1. [Enterprise-Grade Data Science](https://do4ds.com/chapters/sec3/3-0-sec-intro.html)\n (Chapters 15-18)\n\nI chose not to do the exercises in the book.\n\nChapters 1-6 cover basic software engineering concepts including library/package management, the\nthree-tier application model, types of projects (jobs, apps, reports, and APIs), connecting to\ndatabases and APIs, logging and monitoring, deploying code with CI/CD in dev, test, and production\n(including branching strategy) and Docker.\n\nUseful references from the first section include:\n\n- [pins](https://pins.rstudio.com), a package for publishing data, models, and other R objects to\n folders or cloud storage, including AWS, Azure, GCP, Google Drive, OneDrive, and Dropbox.\n- [vetiver](https://vetiver.posit.co), R and Python libraries designed to version, deploy, and\n monitor a trained ML model.\n- [Mastering Shiny](https://mastering-shiny.org/index.html), Hadley Wickham's book on R\n [Shiny](https://shiny.posit.co), published in 2021.\n\nChapters 7-14 cover basic infrastructure engineering concepts, including cloud computing (IaaS,\nPaaS, and SaaS), the command line (terminals, shells, and SSH), Linux (Unix), scaling hardware,\nnetworking, DNS, and TLS (HTTPS).\n\nI disagreed with the recommendations on macOS terminals and configuration management in chapter 8; I\nuse macOS Terminal and `.zprofile` and `.zshrc` respectively. Given my background in infrastructure\nand systems engineering, most of the section was not new to me, except for AWS, which I haven't\nworked with.\n\nThere was one useful reference from the second section:\n\n- [paws](https://github.com/paws-r/paws), an Amazon Web Services SDK for R.\n\nChapters 15-18 cover issues that come up in larger, \"enterprise\", organizations. It includes\ndiscussion of networking and network security (including proxies), authentication and authorization\n(including identity and access management: LDAP, SSO, MFA, RBAC and ABAC), infrastructure as code,\nDocker and Kubernetes, and how enterprise policies affect use of R and Python packages.\n\nThe third section doesn't contain labs, and has one useful reference:\n\n- [httr2](https://httr2.r-lib.org), tools for creating and modifying HTTP requests, then\n performing them and processing the results.\n\n# Future Reading\n\nR books on my reading list.\n\n- [The R Manuals](https://rstudio.github.io/r-manuals/) - a re-styled version of the original R\n manuals, published using Quarto (starting with *Writing R Extensions*)\n- [R Markdown: The Definitive Guide](https://bookdown.org/yihui/rmarkdown/) - written by the author\n of [knitr](https://yihui.org/knitr/)\n- [R Markdown Cookbook](https://bookdown.org/yihui/rmarkdown-cookbook/) - the follow-up to *The\n Definitive Guide*\n- [The Data Validation Cookbook](https://data-cleaning.github.io/validate/) - a book on the R\n [validate](https://CRAN.R-project.org/package=validate) package\n- [Discovering Statistics Using R](https://us.sagepub.com/en-us/nam/discovering-statistics-using-r/book236067) - recommended to me\n as an introduction to statistics using R\n\n# R Dialects\n\nAn explanatory note on the R dialects of base R and tidyverse R.\n\nThe [R programming language](https://en.wikipedia.org/wiki/R_(programming_language)) is over 30\nyears old and has a large number of [packages](https://en.wikipedia.org/wiki/R_package) (R\nlibraries) that extend R. Unlike\n[python](https://en.wikipedia.org/wiki/Python_(programming_language)) (a general purpose language),\nR was designed specifically for analysis, visualization, and statistical modeling, which is why I\n[chose R](https://www.information-safety.org/2020/09/11/working-with-r/) for data analysis: it has\nbuilt-in support for data structures like data frames (implemented in python using\n[pandas](https://en.wikipedia.org/wiki/Pandas_(software))), vectors, packages for just about any\nstatistical tool you'd need, and of course, [ggplot2](https://en.wikipedia.org/wiki/Ggplot2). In\nfairness, python is more popular, more robust, and a better tool for some tasks, like data\nacquisition and machine learning (which were not priorities for my use).\n\nLike many human languages, R has developed two distinct dialects: base R and tidyverse R. Base R\nconsists of the [packages](https://cran.r-project.org/doc/FAQ/R-FAQ.html#Add_002don-packages-in-R)\nincluded in the R distribution\n*(base, compiler, datasets, graphics, grDevices, grid, methods, parallel, splines, stats, stats4, tcltk, tools, utils)*, and the\n[Tidyverse](https://en.wikipedia.org/wiki/Tidyverse) is a collection of packages that implement a\n[domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language) for data\nanalysis, originally created by [Hadley Wickham](https://en.wikipedia.org/wiki/Hadley_Wickham).\n\nIn my experience, tidyverse R is better for data analysis, where base R is better for writing\npackages - tidyverse functions are closer to natural language, but have many more dependencies.\n[Comparing](https://atrebas.github.io/post/2019-03-03-datatable-dplyr/) two popular tools for data\nmanipulation, [dplyr](https://dplyr.tidyverse.org) (tidyverse R) and\n[data.table](https://rdatatable.gitlab.io/data.table/) (base R) shows these differences.\n\nThis code snippet is from a short analysis of survey responses using dplyr:\n\n```r\nsurvey_results <- survey_import |>\n mutate(across(Q1:Q7, ~ case_when(\n .x == \"strongly disagree\" ~ 1,\n .x == \"disagree\" ~ 2,\n .x == \"neither agree nor disagree\" ~ 3,\n .x == \"agree\" ~ 4,\n .x == \"strongly agree\" ~ 5\n ))) |>\n mutate(Q8 = as.numeric(Q8 == \"Yes\")) |>\n arrange(end_date)\n```\n\nThe code is reasonably easy to understand, even if you're not familiar with R.\n\nThe same code written in data.table isn't as clear:\n\n```r\nlikert_5 <- c(\n \"strongly disagree\", \"disagree\", \"neither agree nor disagree\",\n \"agree\", \"strongly agree\"\n)\nq_likert <- paste0(\"Q\", 1:7)\nq_yesno <- \"Q8\"\n\nsurvey_results <- copy(survey_import)\nsurvey_results <- survey_results[\n , (q_likert) := lapply(.SD, \\(x) as.numeric(factor(x, levels = likert_5))),\n .SDcols = q_likert\n][\n , (q_yesno) := lapply(.SD, \\(x) as.numeric(x == \"Yes\")),\n .SDcols = q_yesno\n][\n order(end_date)\n]\n```\n\nWhile it may be harder to read, data.table has some clear advantages: it is quite\n[fast](https://h2oai.github.io/db-benchmark/), especially with very large datasets, and has no\n[dependencies](https://github.com/Rdatatable/data.table/blob/master/DESCRIPTION) other than base R,\nwhere dplyr has many.\n\nThese tradeoffs are why I tend to use tidyverse R for analysis and base R for functions (most\ntidyverse expressions have functional equivalents in base R). Code used in data analysis should be\nclear and easy to read, which tidyverse R excels at. Packaged functions provide documentation and\nthe source code isn't typically read, but many dependencies can be problematic; `R CMD check` will\nraise a NOTE if there are too many imports.\n", "supporting": [ "r-books_files" ], diff --git a/_freeze/site_libs/quarto-listing/list.min.js b/_freeze/site_libs/quarto-listing/list.min.js index 81318815..511346fc 100644 --- a/_freeze/site_libs/quarto-listing/list.min.js +++ b/_freeze/site_libs/quarto-listing/list.min.js @@ -1,2 +1,2 @@ -var List;List=function(){var t={"./src/add-async.js":function(t){t.exports=function(t){return function e(r,n,s){var i=r.splice(0,50);s=(s=s||[]).concat(t.add(i)),r.length>0?setTimeout((function(){e(r,n,s)}),1):(t.update(),n(s))}}},"./src/filter.js":function(t){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,s=r.length;nv.page,a=new g(t[s],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}m(t.slice(0),e)}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,s=0,i=v.items.length;s-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,s,i,a){return this.dottedLeft(t,e,r,n,s,i)||this.dottedRight(t,e,r,n,s,i,a)},dottedLeft:function(t,e,r,n,s,i){return e==r+1&&!this.innerWindow(e,s,i)&&!this.right(e,n)},dottedRight:function(t,e,r,n,s,i,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,s,i)&&!this.right(e,n))}};return function(e){var n=new i(t.listContainer.id,{listClass:e.paginationClass||"pagination",item:e.item||"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});s.bind(n.listContainer,"click",(function(e){var r=e.target||e.srcElement,n=t.utils.getAttribute(r,"data-page"),s=t.utils.getAttribute(r,"data-i");s&&t.show((s-1)*n+1,n)})),t.on("updated",(function(){r(n,e)})),r(n,e)}}},"./src/parse.js":function(t,e,r){t.exports=function(t){var e=r("./src/item.js")(t),n=function(r,n){for(var s=0,i=r.length;s0?setTimeout((function(){e(r,s)}),1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=function(t){for(var e=t.childNodes,r=[],n=0,s=e.length;n]/g.exec(t)){var e=document.createElement("tbody");return e.innerHTML=t,e.firstElementChild}if(-1!==t.indexOf("<")){var r=document.createElement("div");return r.innerHTML=t,r.firstElementChild}}},a=function(e,r,n){var s=void 0,i=function(e){for(var r=0,n=t.valueNames.length;r=1;)t.list.removeChild(t.list.firstChild)},function(){var r;if("function"!=typeof t.item){if(!(r="string"==typeof t.item?-1===t.item.indexOf("<")?document.getElementById(t.item):i(t.item):s()))throw new Error("The list needs to have at least one item on init otherwise you'll have to add a template.");r=n(r,t.valueNames),e=function(){return r.cloneNode(!0)}}else e=function(e){var r=t.item(e);return i(r)}}()};t.exports=function(t){return new e(t)}},"./src/utils/classes.js":function(t,e,r){var n=r("./src/utils/index-of.js"),s=/\s+/;Object.prototype.toString;function i(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}t.exports=function(t){return new i(t)},i.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array();return~n(e,t)||e.push(t),this.el.className=e.join(" "),this},i.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=n(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},i.prototype.toggle=function(t,e){return this.list?(void 0!==e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):(void 0!==e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},i.prototype.array=function(){var t=(this.el.getAttribute("class")||"").replace(/^\s+|\s+$/g,"").split(s);return""===t[0]&&t.shift(),t},i.prototype.has=i.prototype.contains=function(t){return this.list?this.list.contains(t):!!~n(this.array(),t)}},"./src/utils/events.js":function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",s=window.removeEventListener?"removeEventListener":"detachEvent",i="addEventListener"!==n?"on":"",a=r("./src/utils/to-array.js");e.bind=function(t,e,r,s){for(var o=0,l=(t=a(t)).length;o32)return!1;var a=n,o=function(){var t,r={};for(t=0;t=p;b--){var j=o[t.charAt(b-1)];if(C[b]=0===m?(C[b+1]<<1|1)&j:(C[b+1]<<1|1)&j|(v[b+1]|v[b])<<1|1|v[b+1],C[b]&d){var x=l(m,b-1);if(x<=u){if(u=x,!((c=b-1)>a))break;p=Math.max(1,2*a-c)}}}if(l(m+1,a)>u)break;v=C}return!(c<0)}},"./src/utils/get-attribute.js":function(t){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,s=n.length,i=0;i=48&&t<=57}function i(t,e){for(var i=(t+="").length,a=(e+="").length,o=0,l=0;o=i&&l=a?-1:l>=a&&o=i?1:i-a}i.caseInsensitive=i.i=function(t,e){return i((""+t).toLowerCase(),(""+e).toLowerCase())},Object.defineProperties(i,{alphabet:{get:function(){return e},set:function(t){r=[];var s=0;if(e=t)for(;s0?setTimeout((function(){e(r,n,s)}),1):(t.update(),n(s))}}},"./src/filter.js":function(t){t.exports=function(t){return t.handlers.filterStart=t.handlers.filterStart||[],t.handlers.filterComplete=t.handlers.filterComplete||[],function(e){if(t.trigger("filterStart"),t.i=1,t.reset.filter(),void 0===e)t.filtered=!1;else{t.filtered=!0;for(var r=t.items,n=0,s=r.length;nv.page,a=new g(t[s],void 0,n),v.items.push(a),r.push(a)}return v.update(),r}m(t.slice(0),e)}},this.show=function(t,e){return this.i=t,this.page=e,v.update(),v},this.remove=function(t,e,r){for(var n=0,s=0,i=v.items.length;s-1&&r.splice(n,1),v},this.trigger=function(t){for(var e=v.handlers[t].length;e--;)v.handlers[t][e](v);return v},this.reset={filter:function(){for(var t=v.items,e=t.length;e--;)t[e].filtered=!1;return v},search:function(){for(var t=v.items,e=t.length;e--;)t[e].found=!1;return v}},this.update=function(){var t=v.items,e=t.length;v.visibleItems=[],v.matchingItems=[],v.templater.clear();for(var r=0;r=v.i&&v.visibleItems.lengthe},innerWindow:function(t,e,r){return t>=e-r&&t<=e+r},dotted:function(t,e,r,n,s,i,a){return this.dottedLeft(t,e,r,n,s,i)||this.dottedRight(t,e,r,n,s,i,a)},dottedLeft:function(t,e,r,n,s,i){return e==r+1&&!this.innerWindow(e,s,i)&&!this.right(e,n)},dottedRight:function(t,e,r,n,s,i,a){return!t.items[a-1].values().dotted&&(e==n&&!this.innerWindow(e,s,i)&&!this.right(e,n))}};return function(e){var n=new i(t.listContainer.id,{listClass:e.paginationClass||"pagination",item:e.item||"
  • ",valueNames:["page","dotted"],searchClass:"pagination-search-that-is-not-supposed-to-exist",sortClass:"pagination-sort-that-is-not-supposed-to-exist"});s.bind(n.listContainer,"click",(function(e){var r=e.target||e.srcElement,n=t.utils.getAttribute(r,"data-page"),s=t.utils.getAttribute(r,"data-i");s&&t.show((s-1)*n+1,n)})),t.on("updated",(function(){r(n,e)})),r(n,e)}}},"./src/parse.js":function(t,e,r){t.exports=function(t){var e=r("./src/item.js")(t),n=function(r,n){for(var s=0,i=r.length;s0?setTimeout((function(){e(r,s)}),1):(t.update(),t.trigger("parseComplete"))};return t.handlers.parseComplete=t.handlers.parseComplete||[],function(){var e=function(t){for(var e=t.childNodes,r=[],n=0,s=e.length;n]/g.exec(t)){var e=document.createElement("tbody");return e.innerHTML=t,e.firstElementChild}if(-1!==t.indexOf("<")){var r=document.createElement("div");return r.innerHTML=t,r.firstElementChild}}},a=function(e,r,n){var s=void 0,i=function(e){for(var r=0,n=t.valueNames.length;r=1;)t.list.removeChild(t.list.firstChild)},function(){var r;if("function"!=typeof t.item){if(!(r="string"==typeof t.item?-1===t.item.indexOf("<")?document.getElementById(t.item):i(t.item):s()))throw new Error("The list needs to have at least one item on init otherwise you'll have to add a template.");r=n(r,t.valueNames),e=function(){return r.cloneNode(!0)}}else e=function(e){var r=t.item(e);return i(r)}}()};t.exports=function(t){return new e(t)}},"./src/utils/classes.js":function(t,e,r){var n=r("./src/utils/index-of.js"),s=/\s+/;Object.prototype.toString;function i(t){if(!t||!t.nodeType)throw new Error("A DOM element reference is required");this.el=t,this.list=t.classList}t.exports=function(t){return new i(t)},i.prototype.add=function(t){if(this.list)return this.list.add(t),this;var e=this.array();return~n(e,t)||e.push(t),this.el.className=e.join(" "),this},i.prototype.remove=function(t){if(this.list)return this.list.remove(t),this;var e=this.array(),r=n(e,t);return~r&&e.splice(r,1),this.el.className=e.join(" "),this},i.prototype.toggle=function(t,e){return this.list?(void 0!==e?e!==this.list.toggle(t,e)&&this.list.toggle(t):this.list.toggle(t),this):(void 0!==e?e?this.add(t):this.remove(t):this.has(t)?this.remove(t):this.add(t),this)},i.prototype.array=function(){var t=(this.el.getAttribute("class")||"").replace(/^\s+|\s+$/g,"").split(s);return""===t[0]&&t.shift(),t},i.prototype.has=i.prototype.contains=function(t){return this.list?this.list.contains(t):!!~n(this.array(),t)}},"./src/utils/events.js":function(t,e,r){var n=window.addEventListener?"addEventListener":"attachEvent",s=window.removeEventListener?"removeEventListener":"detachEvent",i="addEventListener"!==n?"on":"",a=r("./src/utils/to-array.js");e.bind=function(t,e,r,s){for(var o=0,l=(t=a(t)).length;o32)return!1;var a=n,o=function(){var t,r={};for(t=0;t=p;b--){var j=o[t.charAt(b-1)];if(C[b]=0===m?(C[b+1]<<1|1)&j:(C[b+1]<<1|1)&j|(v[b+1]|v[b])<<1|1|v[b+1],C[b]&d){var x=l(m,b-1);if(x<=u){if(u=x,!((c=b-1)>a))break;p=Math.max(1,2*a-c)}}}if(l(m+1,a)>u)break;v=C}return!(c<0)}},"./src/utils/get-attribute.js":function(t){t.exports=function(t,e){var r=t.getAttribute&&t.getAttribute(e)||null;if(!r)for(var n=t.attributes,s=n.length,i=0;i=48&&t<=57}function i(t,e){for(var i=(t+="").length,a=(e+="").length,o=0,l=0;o=i&&l=a?-1:l>=a&&o=i?1:i-a}i.caseInsensitive=i.i=function(t,e){return i((""+t).toLowerCase(),(""+e).toLowerCase())},Object.defineProperties(i,{alphabet:{get:function(){return e},set:function(t){r=[];var s=0;if(e=t)for(;s - + -rtraining +license – rtraining