diff --git a/docs/blog.html b/docs/blog.html new file mode 100644 index 00000000..095644f6 --- /dev/null +++ b/docs/blog.html @@ -0,0 +1,3214 @@ + + + + + + + + + + + + + + + + + + + + + + June Choe: Blog Posts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Blog Posts

+ + + +
+ +
+
+

Setting up and debugging custom fonts

+
+
data visualization
+
ggplot2
+
typography
+
tutorial
+
+

A practical introduction to all (new) things font in R

+
+
+ + + +
+ +
+
+

Random Sampling: A table animation

+
+
data visualization
+
data wrangling
+
+

Plus a convenient way of rendering LaTeX expressions as images

+
+
+ + + +
+ +
+
+

Collapse repetitive piping with reduce()

+
+
data wrangling
+
tutorial
+
+

Featuring accumulate()

+
+
+ + + +
+ +
+
+

Plot Makeover #2

+
+
plot makeover
+
data visualization
+
ggplot2
+
+

Making a dodged-stacked hybrid bar plot in {ggplot2}

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 week 45

+
+
ggplot2
+
data visualization
+
tidytuesday
+
+

Waffle chart of IKEA furnitures in stock

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 week 44

+
+
ggplot2
+
gganimate
+
spatial
+
data visualization
+
tidytuesday
+
+

Patched animation of the location and cumulative capacity of wind turbines in Canada

+
+
+ + + +
+ +
+
+

Analysis of @everycolorbot's tweets

+
+
data visualization
+
ggplot2
+
rtweet
+
colors
+
+

And why you should avoid neon colors

+
+
+ + + +
+ +
+
+

Designing guiding aesthetics

+
+
data visualization
+
ggplot2
+
tidytuesday
+
+

The fine line between creativity and noise

+
+
+ + + +
+ +
+
+

Demystifying stat_ layers in {ggplot2}

+
+
data visualization
+
ggplot2
+
tutorial
+
+

The motivation behind stat, the distinction between stat and geom, and a case study of stat_summary()

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 week 39

+
+
ggplot2
+
data visualization
+
tidytuesday
+
+

Stacked area plot of the heights of Himalayan peaks attempted over the last century

+
+
+ + + +
+ +
+
+

Plot Makeover #1

+
+
plot makeover
+
data visualization
+
ggplot2
+
+

Flattening a faceted grid for strictly horizontal comparisons

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 week 38

+
+
tables
+
data visualization
+
tidytuesday
+
+

Visualizing two decades of primary and secondary education spending with {gt}

+
+
+ + + +
+ +
+
+

Embedding videos in {reactable} tables

+
+
tables
+
data visualization
+
+

Pushing the limits of expandable row details

+
+
+ + + +
+ +
+
+

Fonts for graphs

+
+
data visualization
+
typography
+
+

A small collection of my favorite fonts for data visualization

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 Week 33

+
+
tidytuesday
+
gganimate
+
ggplot2
+
+

An animation of the main characters in Avatar

+
+
+ + + +
+ +
+
+

Saving a line of piping

+
+
data wrangling
+
dplyr
+
tutorial
+
+

Some notes on lesser known functions/functionalities that combine common chain of {dplyr} verbs.

+
+
+ + + +
+ +
+
+

TidyTuesday 2020 Week 32

+
+
tidytuesday
+
data visualization
+
ggplot2
+
+

A dumbbell chart visualization of energy production trends among European countries

+
+
+ + + +
+ +
+
+

Six years of my Spotify playlists

+
+
ggplot2
+
gganimate
+
spotifyr
+
data wrangling
+
data visualization
+
+

An analysis of acoustic features with {spotifyr}

+
+
+ + + +
+ +
+
+

Shiny tips - the first set

+
+
shiny
+
+

%||%, imap() + {shinybusy}, and user inputs in modalDialog()

+
+
+ + + +
+ +
+
+

geom_paired_raincloud()

+
+
data visualization
+
ggplot2
+
+

A {ggplot2} geom for visualizing change in distribution between two conditions.

+
+
+ + + +
+ +
+
+

Plotting treemaps with {treemap} and {ggplot2}

+
+
data visualization
+
treemap
+
ggplot2
+
tutorial
+
+

Using underlying plot data for maximum customization

+
+
+ + + +
+ +
+
+

Indexing tip for {spacyr}

+
+
data wrangling
+
NLP
+
spacyr
+
+

Speeding up the analysis of dependency relations.

+
+
+ + + +
+ +
+
+

The Correlation Parameter in Mixed Effects Models

+
+
statistics
+
mixed-effects models
+
tutorial
+
+

Notes on the Corr term in {lme4} output

+
+
+
+
+ +
+
+More articles » +
+
+ + +
+

Blog Posts

+ + + +
+ + +
+
+ + +
+ +
+
+ + + + + +
+ + + + + + + + + diff --git a/docs/blog.xml b/docs/blog.xml new file mode 100644 index 00000000..06350460 --- /dev/null +++ b/docs/blog.xml @@ -0,0 +1,293 @@ + + + + June Choe + https://yjunechoe.github.io + + Personal Blog + + + June Choe + https://yjunechoe.github.io/static/img/icon.png + https://yjunechoe.github.io + + Distill + Thu, 24 Jun 2021 00:00:00 +0000 + + Setting up and debugging custom fonts + June Choe + https://yjunechoe.github.io/posts/2021-06-24-setting-up-and-debugging-custom-fonts + A practical introduction to all (new) things font in R + data visualization + ggplot2 + typography + tutorial + https://yjunechoe.github.io/posts/2021-06-24-setting-up-and-debugging-custom-fonts + Thu, 24 Jun 2021 00:00:00 +0000 + + + + Random Sampling: A table animation + June Choe + https://yjunechoe.github.io/posts/2021-01-17-random-sampling-a-table-animation + Plus a convenient way of rendering LaTeX expressions as images + data visualization + data wrangling + https://yjunechoe.github.io/posts/2021-01-17-random-sampling-a-table-animation + Sun, 17 Jan 2021 00:00:00 +0000 + + + + Collapse repetitive piping with reduce() + June Choe + https://yjunechoe.github.io/posts/2020-12-13-collapse-repetitive-piping-with-reduce + Featuring accumulate() + data wrangling + tutorial + https://yjunechoe.github.io/posts/2020-12-13-collapse-repetitive-piping-with-reduce + Sun, 13 Dec 2020 00:00:00 +0000 + + + + Plot Makeover #2 + June Choe + https://yjunechoe.github.io/posts/2020-11-08-plot-makeover-2 + Making a dodged-stacked hybrid bar plot in {ggplot2} + plot makeover + data visualization + ggplot2 + https://yjunechoe.github.io/posts/2020-11-08-plot-makeover-2 + Sun, 08 Nov 2020 00:00:00 +0000 + + + + TidyTuesday 2020 week 45 + June Choe + https://yjunechoe.github.io/posts/2020-11-03-tidytuesday-2020-week-45 + Waffle chart of IKEA furnitures in stock + ggplot2 + data visualization + tidytuesday + https://yjunechoe.github.io/posts/2020-11-03-tidytuesday-2020-week-45 + Tue, 03 Nov 2020 00:00:00 +0000 + + + + TidyTuesday 2020 week 44 + June Choe + https://yjunechoe.github.io/posts/2020-10-28-tidytuesday-2020-week-44 + Patched animation of the location and cumulative capacity of wind turbines in Canada + ggplot2 + gganimate + spatial + data visualization + tidytuesday + https://yjunechoe.github.io/posts/2020-10-28-tidytuesday-2020-week-44 + Wed, 28 Oct 2020 00:00:00 +0000 + + + + Analysis of @everycolorbot's tweets + June Choe + https://yjunechoe.github.io/posts/2020-10-22-analysis-of-everycolorbots-tweets + And why you should avoid neon colors + data visualization + ggplot2 + rtweet + colors + https://yjunechoe.github.io/posts/2020-10-22-analysis-of-everycolorbots-tweets + Thu, 22 Oct 2020 00:00:00 +0000 + + + + Designing guiding aesthetics + June Choe + https://yjunechoe.github.io/posts/2020-10-13-designing-guiding-aesthetics + The fine line between creativity and noise + data visualization + ggplot2 + tidytuesday + https://yjunechoe.github.io/posts/2020-10-13-designing-guiding-aesthetics + Tue, 13 Oct 2020 00:00:00 +0000 + + + + Demystifying stat_ layers in {ggplot2} + June Choe + https://yjunechoe.github.io/posts/2020-09-26-demystifying-stat-layers-ggplot2 + The motivation behind stat, the distinction between stat and geom, and a case study of stat_summary() + data visualization + ggplot2 + tutorial + https://yjunechoe.github.io/posts/2020-09-26-demystifying-stat-layers-ggplot2 + Sun, 27 Sep 2020 00:00:00 +0000 + + + + TidyTuesday 2020 week 39 + June Choe + https://yjunechoe.github.io/posts/2020-09-23-tidytuesday-2020-week-39 + Stacked area plot of the heights of Himalayan peaks attempted over the last century + ggplot2 + data visualization + tidytuesday + https://yjunechoe.github.io/posts/2020-09-23-tidytuesday-2020-week-39 + Wed, 23 Sep 2020 00:00:00 +0000 + + + + Plot Makeover #1 + June Choe + https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1 + Flattening a faceted grid for strictly horizontal comparisons + plot makeover + data visualization + ggplot2 + https://yjunechoe.github.io/posts/2020-09-20-plot-makeover-1 + Sun, 20 Sep 2020 00:00:00 +0000 + + + + TidyTuesday 2020 week 38 + June Choe + https://yjunechoe.github.io/posts/2020-09-14-tidytuesday-2020-week-38 + Visualizing two decades of primary and secondary education spending with {gt} + tables + data visualization + tidytuesday + https://yjunechoe.github.io/posts/2020-09-14-tidytuesday-2020-week-38 + Mon, 14 Sep 2020 00:00:00 +0000 + + + + Embedding videos in {reactable} tables + June Choe + https://yjunechoe.github.io/posts/2020-09-12-videos-in-reactable + Pushing the limits of expandable row details + tables + data visualization + https://yjunechoe.github.io/posts/2020-09-12-videos-in-reactable + Sat, 12 Sep 2020 00:00:00 +0000 + + + + Fonts for graphs + June Choe + https://yjunechoe.github.io/posts/2020-09-06-fonts-for-graphs + A small collection of my favorite fonts for data visualization + data visualization + typography + https://yjunechoe.github.io/posts/2020-09-06-fonts-for-graphs + Sun, 06 Sep 2020 00:00:00 +0000 + + + + TidyTuesday 2020 Week 33 + June Choe + https://yjunechoe.github.io/posts/2020-08-17-tidytuesday-2020-week-33 + An animation of the main characters in Avatar + tidytuesday + gganimate + ggplot2 + https://yjunechoe.github.io/posts/2020-08-17-tidytuesday-2020-week-33 + Mon, 17 Aug 2020 00:00:00 +0000 + + + + Saving a line of piping + June Choe + https://yjunechoe.github.io/posts/2020-08-07-saving-a-line-of-piping + Some notes on lesser known functions/functionalities that combine common chain of {dplyr} verbs. + data wrangling + dplyr + tutorial + https://yjunechoe.github.io/posts/2020-08-07-saving-a-line-of-piping + Fri, 07 Aug 2020 00:00:00 +0000 + + + + TidyTuesday 2020 Week 32 + June Choe + https://yjunechoe.github.io/posts/2020-08-04-tidytuesday-2020-week-32 + A dumbbell chart visualization of energy production trends among European countries + tidytuesday + data visualization + ggplot2 + https://yjunechoe.github.io/posts/2020-08-04-tidytuesday-2020-week-32 + Tue, 04 Aug 2020 00:00:00 +0000 + + + + Six years of my Spotify playlists + June Choe + https://yjunechoe.github.io/posts/2020-07-29-six-years-of-my-spotify-playlists + An analysis of acoustic features with {spotifyr} + ggplot2 + gganimate + spotifyr + data wrangling + data visualization + https://yjunechoe.github.io/posts/2020-07-29-six-years-of-my-spotify-playlists + Wed, 29 Jul 2020 00:00:00 +0000 + + + + Shiny tips - the first set + June Choe + https://yjunechoe.github.io/posts/2020-07-20-shiny-tips-1 + %||%, imap() + {shinybusy}, and user inputs in modalDialog() + shiny + https://yjunechoe.github.io/posts/2020-07-20-shiny-tips-1 + Mon, 20 Jul 2020 00:00:00 +0000 + + + + geom_paired_raincloud() + June Choe + https://yjunechoe.github.io/posts/2020-07-13-geom-paired-raincloud + A {ggplot2} geom for visualizing change in distribution between two conditions. + data visualization + ggplot2 + https://yjunechoe.github.io/posts/2020-07-13-geom-paired-raincloud + Mon, 13 Jul 2020 00:00:00 +0000 + + + + Plotting treemaps with {treemap} and {ggplot2} + June Choe + https://yjunechoe.github.io/posts/2020-06-30-treemap-with-ggplot + Using underlying plot data for maximum customization + data visualization + treemap + ggplot2 + tutorial + https://yjunechoe.github.io/posts/2020-06-30-treemap-with-ggplot + Tue, 30 Jun 2020 00:00:00 +0000 + + + + Indexing tip for {spacyr} + June Choe + https://yjunechoe.github.io/posts/2020-06-25-indexing-tip-for-spacyr + Speeding up the analysis of dependency relations. + data wrangling + NLP + spacyr + https://yjunechoe.github.io/posts/2020-06-25-indexing-tip-for-spacyr + Thu, 25 Jun 2020 00:00:00 +0000 + + + + The Correlation Parameter in Mixed Effects Models + June Choe + https://yjunechoe.github.io/posts/2020-06-07-correlation-parameter-mem + Notes on the Corr term in {lme4} output + statistics + mixed-effects models + tutorial + https://yjunechoe.github.io/posts/2020-06-07-correlation-parameter-mem + Sun, 07 Jun 2020 00:00:00 +0000 + + + + diff --git a/docs/google28f36d9a2442efdb.html b/docs/google28f36d9a2442efdb.html new file mode 100644 index 00000000..38fa9254 --- /dev/null +++ b/docs/google28f36d9a2442efdb.html @@ -0,0 +1 @@ +google-site-verification: google28f36d9a2442efdb.html \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..041e4a21 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,2715 @@ + + + + + + + + + + + + + + + + + + + + + June Choe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

June Choe

+ + +

Ph.D. Student in Linguistics

+
+ + +
+ +
+
+

+
+
+

+ +Education +

+
  • +B.A. (hons.) Northwestern University (2016–20) +
  • +
  • +Ph.D. University of Pennsylvania (2020 ~) +
  • +

    + +Interests +

    +
  • +(Computational) Psycholinguistics +
  • +
  • +Language Acquisition +
  • +
  • +Parsing / Sentence Processing +
  • +
  • +Prosody & Information Structure +
  • +
    +
    +

    + + +Methods: Web-based experiments, eye-tracking, self-paced +reading, corpus analysis +

    +

    + + +Programming: R (fluent) | +HTML/CSS/JS (proficient) | Python +(coursework) +

    +
    +
    +

    +about +

    +
    +

    I am a second year PhD student in Linguistics at +the University of Pennsylvania. I am a psycholinguist broadly +interested in experimental approaches to studying meaning, of various +flavors. I use computational and behavioral methods to study how +comprehenders parse linguistic input, both in real time and at different +stages of language development. My advisor is Anna Papafragou and I am a +member of the Language & +Cognition Lab.

    +

    I received my B.A. in Linguistics from Northwestern University, where +I worked with Jennifer +Cole, Masaya +Yoshida, and Annette +D’Onofrio. I also worked as a research assistant for (and still +collaborate with) the Language, Education, and +Reading Neuroscience Lab) in Communication Sciences and Disorders. I +wrote my thesis on the role of prosodic focus in the processing of +garden-path sentences.

    +

    Beyond linguistics research, I have interests in data visualization, +science communication, and the R programming language. I read and blog about these topics +in my spare time as a hobby. I’m especially passionate about improving +explanatory data viz in academic research and strongly believe that +style is just as important as content. I am also a Penn MindCORE student +affiliate and work as a data science tutor for researchers at Penn.

    +
    +

    +

    +
    +contact me: +yjchoe@sas.upenn.edu +
    +
    + + +
    + +
    +
    + + + + + +
    + + + + + + + + + diff --git a/docs/news.html b/docs/news.html new file mode 100644 index 00000000..557da5b7 --- /dev/null +++ b/docs/news.html @@ -0,0 +1,2666 @@ + + + + + + + + + + + + + + + + + + + + + June Choe: News + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    News

    + + + +
    + + +
    +
    + +
    +

    2021

    +

    July

    + +

    June

    + +

    May

    + +

    January

    + +

    2020

    +

    November

    + +

    October

    + +

    September

    + +

    June

    + +
    + + +
    + +
    +
    + + + + + +
    + + + + + + + + + diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/check_model.png b/docs/posts/2020-06-07-correlation-parameter-mem/check_model.png new file mode 100644 index 00000000..5e79d2c2 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/check_model.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/_check_model-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/_check_model-1.png new file mode 100644 index 00000000..5e79d2c2 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/_check_model-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/all_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/all_plot-1.png new file mode 100644 index 00000000..309b1349 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/all_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bad_fit-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bad_fit-1.png new file mode 100644 index 00000000..71936e67 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bad_fit-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bivariate_dist-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bivariate_dist-1.png new file mode 100644 index 00000000..811b34f1 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/bivariate_dist-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot-1.png new file mode 100644 index 00000000..3f808291 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot_copy-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot_copy-1.png new file mode 100644 index 00000000..3ffa2e85 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/corr_plot_copy-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/data_ellipse-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/data_ellipse-1.png new file mode 100644 index 00000000..cb509e01 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/data_ellipse-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/item_corr_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/item_corr_plot-1.png new file mode 100644 index 00000000..9b33a31b Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/item_corr_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/no_subj_corr_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/no_subj_corr_plot-1.png new file mode 100644 index 00000000..60b240e1 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/no_subj_corr_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/parameter_ellipse-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/parameter_ellipse-1.png new file mode 100644 index 00000000..5355be2c Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/parameter_ellipse-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_item_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_item_plot-1.png new file mode 100644 index 00000000..2efafe0c Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_item_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_subj_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_subj_plot-1.png new file mode 100644 index 00000000..f4cd3461 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/ranef_subj_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot-1.png new file mode 100644 index 00000000..6c56c373 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot_multi-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot_multi-1.png new file mode 100644 index 00000000..d3139113 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/sim_plot_multi-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-10-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-10-1.png new file mode 100644 index 00000000..0de9b516 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-10-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-11-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-11-1.png new file mode 100644 index 00000000..7f889747 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-11-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-12-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-12-1.png new file mode 100644 index 00000000..68243da8 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-12-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-13-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-13-1.png new file mode 100644 index 00000000..9793c440 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-13-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..962ba2bb Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..22297609 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..0b4ea1b2 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-8-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-8-1.png new file mode 100644 index 00000000..bb5ddd92 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-8-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..329442a7 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/wrapup-1.png b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/wrapup-1.png new file mode 100644 index 00000000..1d5347f7 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/figure-html5/wrapup-1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-06-07-correlation-parameter-mem/correlation-parameter-mem_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/index.html b/docs/posts/2020-06-07-correlation-parameter-mem/index.html new file mode 100644 index 00000000..932338ef --- /dev/null +++ b/docs/posts/2020-06-07-correlation-parameter-mem/index.html @@ -0,0 +1,3679 @@ + + + + + + + + + + + + + + + + + + + +June Choe: The Correlation Parameter in Mixed Effects Models + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    The Correlation Parameter in Mixed Effects Models

    + +
    + statistics + mixed-effects models + tutorial +
    + +

    Notes on the Corr term in {lme4} output

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    06-07-2020 +
    + +
    +
    + +
    +

    What is Corr in the output of mixed-effects models?

    +

    When fitting mixed effects regression models, especially those that try to keep it “maximal” (as per Barr, Levy, Scheepers, & Tily 2013), the random effects in the output of the model sometimes displays a column named Corr where some rows have numbers that range from -1 to 1.

    +

    +

    It’s easy to guess that Corr stands for correlation and that the numbers in the column are correlation coefficients. If there are multiple predictors and the random effects structure includes more than one of those terms (e.g., (1 + Effect_1 * Effect_2 | Subject)), we even get another clue for this from the way that the Corr values spread out in the shape of a right triangle, much like in a correlation matrix.

    +

    +

    Despite the fact that we’re bound to have encountered this at some point when working with or reading about mixed effects models, I’ve found that there aren’t many beginner-friendly material explaining what they are - there are one-paragraph StackExchange answers and dense statistics papers, but not much in between in terms of comprehensiveness.

    +

    So here are my compiled notes on correlation parameters in linear mixed effects models that I’ve made for myself (with a basic knowledge of LMEMs).

    +

    Before we get started

    +

    Our toy data and model

    +
    + +
    +

    For the purposes of this discussion, I have created a toy experiment data (the code used to generate it is attached at the bottom).

    +

    The dataset toydata has 1,920 rows with the following columns:

    + +
    + +
    +
    +
    +
    toydata
    +
    +
    +
      # A tibble: 1,920 x 4
    +     Subject Item  Condition Response
    +     <fct>   <fct> <fct>        <dbl>
    +   1 1       1     Control       226.
    +   2 1       2     Treatment     300.
    +   3 1       3     Control       239.
    +   4 1       4     Treatment     262.
    +   5 1       5     Control       241.
    +   6 1       6     Treatment     264.
    +   7 1       7     Control       237.
    +   8 1       8     Treatment     230.
    +   9 1       9     Control       229.
    +  10 1       10    Treatment     283.
    +  # ... with 1,910 more rows
    +
    +

    Imagine toydata to be the results from a very simple experiment. In this imaginary experiment, there are 80 subjects and each subject is tested on 24 items, resulting in a total of 1,920 trials/observations. This is a within-partipant design, so each participant sees 12 of the items in the Control condition and the other 12 in the Treatment condition.

    +

    Let’s say that with our toy data, we want to know whether Condition has a positive effect on Response. Our goal by using mixed-effects modeling is to isolate the effect of Condition on Response (fixed effect), while controlling for by-item and by-subject variations (random effects). So let’s fit a simple linear mixed-effects model with the maximal random effects structure, with random intercepts and slopes for Condition by Subject and Item:

    +
    +
    +
    model <- lmer(Response ~ Condition + (1+Condition|Subject) + (1+Condition|Item),
    +              REML = FALSE, control = lmerControl('bobyqa'), data = toydata)
    +
    +
    +
    +

    And let’s really quickly check model assumptions:

    +
    +
    +
    performance::check_model(model)
    +
    +
    +
    +

    +

    Everything looks okay, so let’s look at the model output:

    +
    +
    +
    summary(model)
    +
    +
    +
      Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's
    +    method [lmerModLmerTest]
    +  Formula: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition |  
    +      Item)
    +     Data: toydata
    +  Control: lmerControl("bobyqa")
    +  
    +       AIC      BIC   logLik deviance df.resid 
    +     13267    13317    -6624    13249     1911 
    +  
    +  Scaled residuals: 
    +     Min     1Q Median     3Q    Max 
    +  -3.176 -0.627 -0.065  0.576  4.864 
    +  
    +  Random effects:
    +   Groups   Name               Variance Std.Dev. Corr
    +   Subject  (Intercept)        637.1    25.24        
    +            ConditionTreatment 108.1    10.40    0.85
    +   Item     (Intercept)         44.4     6.66        
    +            ConditionTreatment 308.2    17.56    0.14
    +   Residual                     37.4     6.11        
    +  Number of obs: 1920, groups:  Subject, 80; Item, 24
    +  
    +  Fixed effects:
    +                     Estimate Std. Error     df t value Pr(>|t|)    
    +  (Intercept)          209.64       3.14 100.84    66.8  < 2e-16 ***
    +  ConditionTreatment    35.88       3.78  28.52     9.5  2.5e-10 ***
    +  ---
    +  Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    +  
    +  Correlation of Fixed Effects:
    +              (Intr)
    +  CndtnTrtmnt 0.291
    +
    +

    The high t-statistic and low p-value of ConditionTreatment in the fixed effects output suggests that our data is extremely unlikely given the null hypothesis that Condition has no effect on Response (and the sign of the estimate further suggests a positive effect of the Treatment condition on Response compared to the Control condition). Therefore, this is strong evidence in support of our hypothesis.

    +

    Here’s a nicer-looking summary table made with tab_model() from the {sjPlot} package. I will keep using this format from this point on. Not only is this nicer to look at, the notations used here (like \(\tau_{00}\) and \(\rho_{01}\)) are from Barr et al. (2013), so it’s easier to connect the pieces IMO.

    +
    +
    +
    sjPlot::tab_model(model)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +  + +Response +
    +Predictors + +Estimates + +CI + +p +
    +(Intercept) + +209.64 + +203.49 – 215.80 + +<0.001 +
    +Condition [Treatment] + +35.88 + +28.48 – 43.28 + +<0.001 +
    +Random Effects +
    2 + +37.37 +
    00 Subject + +637.14 +
    00 Item + +44.39 +
    11 Subject.ConditionTreatment + +108.10 +
    11 Item.ConditionTreatment + +308.21 +
    01 Subject + +0.85 +
    01 Item + +0.14 +
    +ICC + +0.97 +
    +N Subject + +80 +
    +N Item + +24 +
    +Observations + +1920 +
    +Marginal R2 / Conditional R2 + +0.216 / 0.975 +
    +
    +

    Okay so our finding is great and all but we’re more interested in the random effects here so let’s look at that.

    +

    The random effects (a review)

    +

    We can isolate the random effects from the model using VarCorr():

    +
    +
    +
    VarCorr(model)
    +
    +
    +
       Groups   Name               Std.Dev. Corr
    +   Subject  (Intercept)        25.24        
    +            ConditionTreatment 10.40    0.85
    +   Item     (Intercept)         6.66        
    +            ConditionTreatment 17.56    0.14
    +   Residual                     6.11
    +
    +

    Let’s ignore the Corr column for a moment and talk about Std.Dev first.

    +

    The Std.Dev. values for the Subject random effects group suggest that the variation in the subject intercepts are fitted with a larger standard deviation of 25.24 and that the variation in subject slopes for Condition are fitted with a smaller standard deviation of 10.4.

    +

    Let’s plot the by-subject variation:

    +
    +

    +
    +

    We see a clear variation in the intercepts, and a subtler variation in the slopes. This is overall pretty consistent with the stand deviation values for subject random effects that we found earlier.

    +

    Let’s plot the by-item variation as well:

    +
    +

    +
    +

    Here, we see the opposite: a clear variation in the slopes, and a subtler variation in the intercepts. Again, this is overall pretty consistent given the item random effects output: a larger standard deviation for the item slopes and a smaller standard deviation for item intercepts, as we found earlier.

    +

    Now that we’ve reviewed Std.Dev., let’s talk about Corr, which is our main focus.

    +

    The Correlation Parameter

    +

    Looking at the Corr column now, we see two numbers: 0.85 within the Subject random effects group and 0.14 within the Item random effects group.

    +
    +
       Groups   Name               Std.Dev. Corr
    +   Subject  (Intercept)        25.24        
    +            ConditionTreatment 10.40    0.85
    +   Item     (Intercept)         6.66        
    +            ConditionTreatment 17.56    0.14
    +   Residual                     6.11
    +
    +

    As you might have guessed, they have something to do with the correlation between random effects (intercept and slope) within each group (subject and item).

    +

    But if we extract the subject random effects, for example, and measure the correlation between subject intercepts and subject slopes, we get a slightly different number:

    +
    +
    +
    # Extract by-subject intercept and slope
    +ranef_subj <- ranef(model)$Subject
    +
    +ranef_subj_intercepts <- ranef_subj$`(Intercept)`
    +ranef_subj_slopes <- ranef_subj$ConditionTreatment
    +
    +# Calculate correlation
    +cor(ranef_subj_intercepts, ranef_subj_slopes)
    +
    +
    +
      [1] 0.88
    +
    +

    In fact, we get slightly different values for the standard deviation of the subject random intercepts and slopes as well:

    +
    +
    +
    # Calculate the standard deviation of by-subject intercepts and slopes
    +summarize_all(ranef_subj, sd)
    +
    +
    +
        (Intercept) ConditionTreatment
    +  1        25.3              10.18
    +
    +

    So it looks like what the model isn’t just taking the random effects in our toydata dataset and calculating their variations and correlations. So then what is it doing?

    +

    How the model estimates random effects

    +

    What we have to keep in mind when doing mixed effects modeling is that the model is fitting the random effects in the data, rather than just describing them. More specifically, the model is estimating population parameters that generated the sample of random effects that are seen in the data.1

    +

    And in fact that’s exactly what we want to do. We don’t care about how individual subjects or items behave in our experiment, in the sense that we don’t care how fast John Doe presses a button, for example. We don’t want to predict John Doe’s behavior, but we do want to estimate, using data from John Doe, Jane Doe, Average Joe, and other participants from our experiment, the overall distribution of people’s idiosyncratic tendencies so that we can statistically control for them to get a better estimate for the fixed effects that we care about.

    +

    Take the random intercepts by subject for example. The model estimated the distribution of subject intercepts to follow a normal distribution with a standard deviation of 25.24, which is a an estimate of the Population. The variation in subject intercepts in the data itself that we manually calculated above (25.3) is the Sample standard deviation. Of course, if the sample follows a normal distribution and if we also assume the population to be normally distributed, the sample variance should be the best estimate for the population variance. And in fact they do end up being very close!

    +

    So the numbers in the Std.Dev. colum are the model’s fit for the variation within each random effect.

    +

    With this, we now have a better understanding of the numbers in the Corr column: they are the model’s fit for the correlation between random effects.

    +

    To go more in depth with our discussion, let’s plot the intercepts and slopes for our 80 subjects:

    +
    +

    +
    +

    Recall that when we manually calculated the correlation between subject intercepts and subject slopes within our sample of 80 subjects in the data, we got 0.88. That is in fact what is shown by the plot above.

    +

    And as we discussed earlier, the numbers in the Std.Dev. column are the model’s fit for the variation within each random effect. So the model is saying that the variation for subject intercepts follows a normal distribution with mean = 0 and standard deviation = 25.24. Likewise, the model is saying that the variation for subject slopes follows a normal distribution with mean = 0 and standard deviation = 10.4.2

    +

    So the model estimates these two distributions - one for subject slopes and one for subject intercepts - to capture the overall distribution of subject random effects.

    +

    This is illustrated below, where the normal curve at the top is the distribution of subject intercepts estimated by the model, and the normal curve to the right is the distribution of subject slopes estimated by the model. For every subject, their intercepts and slopes are understood to be generated from these two underlying parameters:

    +
    +

    +
    +

    But is specifying each distribution for intercept and item enough to capture the overall distribution of subject random effects?

    +

    One way to test this is to work backwards and generate some observations from the model’s parameters. The idea here is this: if the two normal distributions (one for subject intercept and one for subject slope) can sufficiently capture the distribution of the subject random effects, then sampling from them should yield a distribution that is in the shape of the actual distribution in our data.

    +

    Let’s draw 80 samples of subject intercepts and subject slopes from their respective distributions and then plot them together. Here’s one result:

    +
    +

    +
    +

    These points are consistent with what the two distributions predict: there are more points towards the center (the means of the distributions) and less points towards the corners (the tails of the distributions).

    +

    But this doesn’t look like the actual distribution of our subject random effects.

    +

    We can repeat this sampling procedure many times, but none of them look close to the distribution of the subject random effects in our data:

    + +
    +

    +
    + +

    So what are we missing here?

    +

    Well, what’s missing here is the correlation between the intercepts and slopes that I conveniently left out to demonstrate that just specifying the individual distributions for subject intercepts and subject slopes poorly captures the actual distribution of subject random effects in our data.

    +

    In more technical terms, treating the two random effects as independently sampled from their respective distributions fails to fit the data well because the two random effects are highly correlated. They should instead be treated as being jointly sampled from a bivariate distribution

    +

    And that’s exactly what adding the correlation parameter does. Let’s break this down.

    +

    When we say that two variables are independently sampled from two distributions (as we just did above), then their joint distribution looks something like this, where most of the data is expected to fall within the grey shaded ellipse:

    +
    +

    +
    +

    This is clearly a bad fit for the distribution of our subject random effects…

    +
    +

    +
    +

    … because the distribution of the subject random effects actually takes the shape of a tilted ellipse instead (dotted outline):

    +
    +

    +
    +

    In fact, we cannot generate any distribution of a tilted shape with just two independent distributions for each variable. We need to factor in covariation to capture the correlation between variables. Barr et al. (2013) illustrates this clearly in the supplementary materials to their paper. You can see from the plot below (originally Figure 1 on the linked page) that without the correlation parameter, you can only capture distributions that are symmetrical with respect to the axes (the darker ellipses). However, once you add in a correlation parameter (\(\rho\)), you can capture distributions that are in the “tilted” shape (the lighter ellipses) like the distribution of our highly correlated subject intercepts and subject slopes.

    +
    +
    +Figure from Barr et al. (2013) +

    +Figure 1: Figure from Barr et al. (2013) +

    +
    +
    +

    Putting it all together

    +

    Here’s the output of model again:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +  + +Response +
    +Predictors + +Estimates + +CI + +p +
    +(Intercept) + +209.64 + +203.49 – 215.80 + +<0.001 +
    +Condition [Treatment] + +35.88 + +28.48 – 43.28 + +<0.001 +
    +Random Effects +
    2 + +37.37 +
    00 Subject + +637.14 +
    00 Item + +44.39 +
    11 Subject.ConditionTreatment + +108.10 +
    11 Item.ConditionTreatment + +308.21 +
    01 Subject + +0.85 +
    01 Item + +0.14 +
    +ICC + +0.97 +
    +N Subject + +80 +
    +N Item + +24 +
    +Observations + +1920 +
    +Marginal R2 / Conditional R2 + +0.216 / 0.975 +
    +
    +

    And let’s keep focusing on the subject random effects for now.

    +

    There are three parameters that the model estimated to capture the by-subject variation:

    +
      +
    1. The variation (Std.Dev.) for subject intercept

    2. +
    3. The variation (Std.Dev.) for subject slope

    4. +
    5. The correlation (Corr) between subject intercept and subject slope.

    6. +
    +

    With these three parameters, the model is defining a bivariate normal distribution, from which subject intercepts (\(S_{0s}\)) and subject slopes (\(S_{1s}\)) are sampled from (Equation 3 from Barr et al., 2013):

    +

    \[(S_{0s}, S_{1s})\ \sim\ N(0,\begin{bmatrix}\tau_{00}^2 & \rho\ \tau_{00}^2 \tau_{11}^2 \\ \rho\ \tau_{00}^2 \tau_{11}^2 & \tau_{11}^2 \end{bmatrix})\]

    +

    For the variance-covariance matrix, we can substitute the standard deviation for the subject intercept \(\tau_{00}^2\) with 25.24, the standard deviation for the subject slope \(\tau_{11}\) with 10.4, and the correlation \(\rho\) with 0.85 to get the following:

    +

    \[(S_{0s}, S_{1s})\ \sim\ N(0,\begin{bmatrix}25.24^2 & 0.85\ \times\ 25.24\ \times\ 10.4 \\ 0.85\ \times\ 25.24\ \times\ 10.4 & 10.4^2 \end{bmatrix})\]

    +

    If subject intercepts and subject slopes are jointly sampled from the above distribution, most observations should fall within this grey area:

    +
    +

    +
    + +

    Let’s again repeatedly sample from this new bivariate distribution (which you can do with mvrnorm() from the {MASS} package) to check:

    +
    +

    +
    +

    Like we expected, this new distribution generates observations of subject slopes and subject intercepts that are highly correlated. But more importantly, the distribution of subject random effects in our data looks like it could be one of these samples, meaning that this bivariate normal distribution fits our data well.

    +

    Good thing that we had the model estimate this parameter by specifying the random effects structure for subjects as (1 + Condition | Subject) in our model formula!

    +

    What if we leave out this correlation parameter? Would it significantly worsen model fit?

    +

    We can check by building another model without the correlation term between the subject random effects and comparing it with our original model.3

    +

    The no_subj_cor_model below is a depleted model without the correlation parameter between the random intercepts and random slopes by subject. You can see that the subject group is missing a value in the Corr column.4

    +
    +
    +
    no_subj_cor_model <- lmer(Response ~ Condition + (1+model.matrix(model)[,2]||Subject) + (1+Condition|Item),
    +                          REML = FALSE, control = lmerControl('bobyqa'), data = toydata)
    +
    +tab_model(no_subj_cor_model)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +  + +Response +
    +Predictors + +Estimates + +CI + +p +
    +(Intercept) + +209.64 + +203.44 – 215.84 + +<0.001 +
    +Condition [Treatment] + +35.88 + +28.43 – 43.33 + +<0.001 +
    +Random Effects +
    2 + +37.34 +
    00 Subject + +649.20 +
    00 Subject.1 + +110.96 +
    00 Item + +44.56 +
    11 Item.ConditionTreatment + +311.76 +
    01 Item + +0.14 +
    +ICC + +0.96 +
    +N Subject + +80 +
    +N Item + +24 +
    +Observations + +1920 +
    +Marginal R2 / Conditional R2 + +0.263 / 0.970 +
    +
    +

    Now let’s perform a likelihood ratio test using anova():

    +
    +
    +
    anova(no_subj_cor_model, model, test = 'Chisq')
    +
    +
    +
      Data: toydata
    +  Models:
    +  no_subj_cor_model: Response ~ Condition + (1 + model.matrix(model)[, 2] || Subject) + 
    +  no_subj_cor_model:     (1 + Condition | Item)
    +  model: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition | 
    +  model:     Item)
    +                    npar   AIC   BIC logLik deviance Chisq Df Pr(>Chisq)    
    +  no_subj_cor_model    8 13352 13396  -6668    13336                        
    +  model                9 13267 13317  -6624    13249  87.2  1     <2e-16 ***
    +  ---
    +  Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
    +
    +

    The first thing to notice is that no_subj_cor_model has one less Df, or degrees of freedom, than model. This is because every correlation between random effects is an additional parameter that the model is estimating. So removing the correlation between random effects for no_subj_cor_model leaves it with 8 parameters, one less than the original, full model. There’s a good discussion of what parameters are specified by different lmer() formulas in this StackExchange thread.

    +

    After performing this sanity check, the next thing to note is the very low number in Pr(>Chisq), telling us that the models are significantly different from one another. This might come off as weird if you’re only used to performing ANOVA comparisons to check whether a predictor is significant or not. In fact, there are no obvious differences between the output of no_subj_cor_model and the output of our original model other than the presence/absence of the correlation between subject random effects.

    +

    But clearly something major is going on behind the curtains, so we turn to the last term(s) of interest - AIC and BIC, which are scores for model fit. The numbers are hard to interpret on their own, but useful when comparing models. Here, both the AIC and the BIC of no_subj_cor_model are higher than model, suggesting that no_subj_cor_model has a worse fit, and a statistically significant one at that.

    +

    More specifically, we know that the only meaningful difference between no_subj_cor_model and model is the correlation parameter for the subject random effects, so no_subj_cor_model must be capturing the subject random effects relativelty poorly under its assumption that subject intercepts and subject slopes do not correlate with one another (i.e., that they are independent).

    +

    So let’s look at the random effects calculated by no_subj_cor_model and its poor attempt at fitting their distribution.

    +

    First, let’s plot the subject intercepts by subject slopes like we did for our original model:

    +
    +

    +
    +

    You might notice that the no_subj_cor_model calculates subject random effects that are very similar to those calculated by our original mode. Here’s a side-by-side comparison of the subject random effects from model and no_subj_cor_model:

    +
    +

    +
    +

    This illustrates a very important point. Removing the correlation parameter does not change the calculation of the random effects (barring any serious convergence failures, of course). This shouldn’t be surprising because random effects, like fixed effects, speak to facts (in the frequentist sense) about how the data that we observe is generated. It is literally the case here since I included these random effects explicitly in making toydata. But more importantly, the idea that there are random variations generated from underlying population-level parameters is an assumption that we are making when we use mixed-effects models.

    +

    The only meaningful difference between the two models here, then, is in their fit - e.g., how well the model captures the distribution of the subject random effects. We actually went over this above - we saw that our original model fits subject random effects using a bivariate normal distribution assuming a correlation, while no_subj_cor_model should be fitting subject random effects using two univariate normal distributions, assuming no (i.e., zero) correlation.

    +

    Here’s a visual comparison of model fit, with the plot for model at the top and the plot for no_subj_cor_model at the bottom:

    +
    + +
    +
    +

    +
    +
    +

    +
    +

    Where the term \(\rho = 0\) in the plot for no_subj_cor_model indicates that the subject intercepts and subject slopes are generated from this bivariate distribution:

    +

    \[(S_{0s}, S_{1s})\ \sim\ N(0,\begin{bmatrix} \tau_{00}^2 & 0 \\ 0 & \tau_{11}^2 \end{bmatrix})\]

    +

    Which is the same as independetly sampling from these two univariate normal distributions:

    +

    \[S_{0s} \sim N(0, \tau_{00})\]

    +

    \[S_{1s} \sim N(0, \tau_{11})\]

    +

    Now, looking at the previous pair of plots, no_subj_cor_model (bottom) clearly fits the distribution of the subject random effects poorly compared to our original model model (top), and that appears to be the driving the significant decrease in fit that we found from the likelihood ratio test earlier. It seems to be the case that the inclusion of the correlation parameter between subject random intercepts is necessary to fit the data well.

    +

    Are correlation parameters always necessary?

    +

    The question of how “maximal” our models should be is very tricky, and especially so when it concerns the inclusion/exclusion of correlation parameters (see discussions here and here). For example, Bates, Kliegl, Vasishth, & Baayen (2015) and Matuschek, Kliegl, Vasishth, & Baayen (2017) have called for parsimonious models with stricter criteria for including terms in the model, beyond whether they cause the model to fail to converge.5

    +

    I’ll demonstrate one case here where it doesn’t seem like including a correlation parameter particularly improves model fit.

    +

    Let’s repeat the model comparison process above, except this time taking out the correlation parameter for item.

    +

    For context, here is the random effects output of model again:

    +
    +
       Groups   Name               Std.Dev. Corr
    +   Subject  (Intercept)        25.24        
    +            ConditionTreatment 10.40    0.85
    +   Item     (Intercept)         6.66        
    +            ConditionTreatment 17.56    0.14
    +   Residual                     6.11
    +
    +

    Again, there are three parameters that the model estimated to capture the by-item variation:

    +
      +
    1. The variation (Std.Dev.) for item intercept

    2. +
    3. The variation (Std.Dev.) for item slope

    4. +
    5. The correlation (Corr) between item intercept and item slope.

    6. +
    +

    And here is what the distribution of item random effects from model look like:

    +
    +

    +
    +

    Our model fitted a bivariate normal distribution with the standard deviation of item intercepts = 6.66, the standard deviation of item slopes = 10.4, and correlation = 0.14.

    +

    We can again visualize the fit of model to the distribution of the item random effects:

    +
    +

    +
    +

    The model estimates a low correlation of 0.14, which is reflected in the small tilt of the ellipse. It looks like the model is capturing the distribution of the item random effects pretty well. But is the correlation parameter really that necessary here?

    +

    Let’s make another depleted model, no_item_cor_model, with the correlation between item random effects removed:

    +
    +
    +
    no_item_cor_model <- lmer(Response ~ Condition + (1+Condition|Subject) + (1+model.matrix(model)[,2]||Item),
    +                          REML = FALSE, control = lmerControl('bobyqa'), data = toydata)
    +
    +tab_model(no_item_cor_model)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +  + +Response +
    +Predictors + +Estimates + +CI + +p +
    +(Intercept) + +209.64 + +203.49 – 215.80 + +<0.001 +
    +Condition [Treatment] + +35.88 + +28.45 – 43.31 + +<0.001 +
    +Random Effects +
    2 + +37.37 +
    00 Subject + +636.98 +
    00 Item + +44.55 +
    00 Item.1 + +310.22 +
    11 Subject.ConditionTreatment + +108.08 +
    01 Subject + +0.85 +
    +ICC + +0.96 +
    +N Subject + +80 +
    +N Item + +24 +
    +Observations + +1920 +
    +Marginal R2 / Conditional R2 + +0.244 / 0.972 +
    +
    +

    Again, the output of the depleted model printed here does not differ that much from the output of model. We can see also get a sense of this by visualizing the fit of no_item_cor_model to the distribution of item random effects:

    +
    +

    +
    +

    We can see this more clearly with a side-by-side comparison of model fit by model (blue) and no_item_cor_model (red):

    +
    +

    +
    +

    Doesn’t seem like there are big differences here, but we have to run some statistics to be sure. So let’s perform another log likelihood ratio test:

    +
    +
    +
    anova(no_item_cor_model, model)
    +
    +
    +
      Data: toydata
    +  Models:
    +  no_item_cor_model: Response ~ Condition + (1 + Condition | Subject) + (1 + model.matrix(model)[, 
    +  no_item_cor_model:     2] || Item)
    +  model: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition | 
    +  model:     Item)
    +                    npar   AIC   BIC logLik deviance Chisq Df Pr(>Chisq)
    +  no_item_cor_model    8 13265 13310  -6625    13249                    
    +  model                9 13267 13317  -6624    13249  0.47  1       0.49
    +
    +
    + +
    +

    First, for sanity check, we see that no_item_cor_model has one less Df than model, which is what we’d expect if no_item_cor_model indeed lacks the correlation parameter for item random effects. Next, we see that the value of Pr(>Chisq) is very high, at 0.49, suggesting that the models are not significantly different. This is corroborated by the very small differences between the models’ AIC and BIC values. These small differences here are likely reducible to the fact that AIC and BIC penalize more number of parameters (as a way of balancing model fit with model complexity). In fact, the differences in AIC between the models is approximately 2, which is exactly what you’d expect if you added a redundant parameter with no additional explanatory power to the model.

    +

    In sum, we see that when modeling our dataset toydata, estimating a correlation parameter for subject random effects improves model fit, while doing so for item random effects doesn’t as much.

    +

    Conclusion and implications for model building

    +

    My main goal here was to simply go over what the correlation parameter in mixed-effects models is, so the question of whether we should be including certain correlation parameter(s) in our models are beyond the scope of this discussion (and should be handled on a case-by-case basis). It’s also something that I’m in the process of learning, so I don’t have a good answer to it yet. But my personal view (which may change later with more knowledge and experience) is to keep correlation parameters in the model unless they make the model fail to converge. So in the case of the correlation parameter for item random effects in model that we discussed above, I’d personally keep that in since we didn’t run into any convergence issues fitting the maximal model. In general, if there’s no meaningful difference either way, I err towards leaving the correlation parameter in there. In other words, I try to keep the model as maximal as possible without overparameterizing it (Barr et al., 2013).

    +

    I don’t think that the spirit of this message is really controversial, and the more challenging part of this is putting it into practice. We not only need to balance model fit with model complexity, but we also often need to navigate conflicts between important considerations from statistical theory and from whatever domain our research is in (linguistics, psychology, etc.).

    +

    To resolve this, a lot of people have streamlined different methods of reducing the complexity of the random effects structure in a statistically motivated way. One such example is using Principal Components Analysis (PCA) (suggested in Bates et al., 2015). In Section 3 of their paper, Bates and colleagues outline a procedure for iterative model reduction which involves PCA (now available as rePCA() in the lme4 package) to determine how many random effect terms are sufficient to capture the variance in the random effects. This is still not a perfect solution, of course, but it’s a good next step for putting this knowledge into practice. Or you can just do fancy Bayesian analyses and avoid all these problems, so I hear

    +

    Anyways, that’s it for my notes. Here’s the code that generated toydata:

    +
    +
    +
    ###########
    +## Setup ##
    +###########
    +
    +# Load Packages (make sure dplyr::filter() isn't makes by MASS:filter())
    +library(MASS)
    +library(tidyverse)
    +library(lme4)
    +
    +# Set seed
    +set.seed(1234)
    +
    +# Set number of participants and items
    +n_subjects <- 80
    +n_items <- 24
    +
    +#################
    +## Make trials ##
    +#################
    +
    +# Generate levels
    +Subject <- gl(n_subjects, n_items)
    +Item <- rep(gl(n_items, 1), n_subjects)
    +Condition <- factor(rep(c(rep(c("Control", "Treatment"), n_items/2),
    +                   rep(c("Treatment", "Control"), n_items/2)),
    +                 n_subjects/2))
    +
    +# Treatment coding
    +Condition_coded <- ifelse(Condition == "Control", 0, 1)
    +
    +# Combine into trials
    +Data <- tibble(Subject, Item, Condition, Condition_coded)
    +
    +#############################
    +## Add Intercept and Slope ##
    +#############################
    +
    +# Add intercept
    +Data$Intercept <- 200
    +
    +# Add slope
    +Data$Slope <- ifelse(Data$Condition == "Treatment", 30, 0)
    +
    +########################
    +## Add Random Effects ##
    +########################
    +
    +# By-subject variation in intercept and slope (sampled from bivariate normal)
    +sd_subj_intercept <- 25
    +sd_subj_slope <- 10
    +subj_ranef_cor <- 0.8
    +
    +subj_ranef <- mvrnorm(n_subjects,
    +                      # means of two normals are both 0
    +                      c("Intercept" = 0, "Slope" = 0),
    +                      # 2x2 variance-covariance matrix
    +                      matrix(
    +                        c(sd_subj_intercept^2,
    +                          subj_ranef_cor*sd_subj_intercept*sd_subj_slope,
    +                          subj_ranef_cor*sd_subj_intercept*sd_subj_slope,
    +                          sd_subj_slope^2),
    +                        ncol = 2)
    +                      )
    +
    +Data$Subj_intercept <- rep(subj_ranef[,"Intercept"], each = n_items)
    +Data$Subj_slope <- rep(subj_ranef[,"Slope"], each = n_items)
    +
    +# By-item variation in intercept and slope (sampled independently)
    +Data$Item_intercept <- rep(rnorm(n_items, sd = 5), times = n_subjects)
    +Data$Item_slope <- rep(rnorm(n_items, sd = 15), times = n_subjects)
    +
    +# Random noise
    +Data$Noise <- rnorm(nrow(Data), 0, 5) + rlnorm(nrow(Data), 0.5)
    +
    +###########################
    +## Generate Observations ##
    +###########################
    +
    +Data <- Data %>%
    +  mutate(Response =
    +           Intercept +
    +           Slope * Condition_coded +
    +           Subj_intercept +
    +           Subj_slope * Condition_coded +
    +           Item_intercept +
    +           Item_slope * Condition_coded +
    +           Noise)
    +
    +#################
    +## Toy Dataset ##
    +#################
    +
    +toydata <- Data %>% 
    +  select(Subject, Item, Condition, Response)
    +
    +
    +
    +
    +
    +
    +
      +
    1. This distinction is also reflected in the fact that the notation for random effect standard deviation is tau (\(\tau\)), which is a Greek symbol. In statistics, Greek symbols (like \(\beta\), which we may be more familiar with) refers to population-level paramters.↩︎

    2. +
    3. But what if the distribution of random effects has a mean that is not equal to zero? Well that just shifts the fixed effects estimate, so the distribution of random effects can be fully characterized by just its variance/standard deviation. This is also why you should never remove a term from fixed effects without removing it from random effects like in Response ~ 1 + (1 + Condiiton | Subject) without a good reason, because the model will assume the fixed effect of Condition to be zero.↩︎

    4. +
    5. Removing a correlation term in lmer() turns out to be actually sort of tricky if you don’t explicitly numerically code your factors - sometimes just using the double bar syntax (||) doesn’t always work. I won’t go into the details of how to do that here, but there are good discussions of doing this using model.matrix() in this Rpubs post and Section 5.4 (also Appendix E) of Frossard and Renaud (2019). I could have done numeric coding with something like mutate(data, Condition = as.integer(Condition == "Treatment")), but I wanted to try this way out for myself↩︎

    6. +
    7. Here, \(\tau_{00\ Subject.1}\) is actually the same as the \(\tau_{00\ Subject.ConditionTreatment}\) term from the maximal model, model. I don’t know how to suppress this name change after dropping a correlation term - if you do, please let me know!↩︎

    8. +
    9. The (simplified) argument here is that having the model estimate superfluous variance components can make it more difficult for the model to detect an effect if it actually exists - i.e., can lead to a loss of power↩︎

    10. +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/nocor.png b/docs/posts/2020-06-07-correlation-parameter-mem/nocor.png new file mode 100644 index 00000000..37fcdace Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/nocor.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/preview.png b/docs/posts/2020-06-07-correlation-parameter-mem/preview.png new file mode 100644 index 00000000..2ef8979e Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/preview.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/ranef_1.png b/docs/posts/2020-06-07-correlation-parameter-mem/ranef_1.png new file mode 100644 index 00000000..2184987d Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/ranef_1.png differ diff --git a/docs/posts/2020-06-07-correlation-parameter-mem/ranef_2.png b/docs/posts/2020-06-07-correlation-parameter-mem/ranef_2.png new file mode 100644 index 00000000..b0e0f378 Binary files /dev/null and b/docs/posts/2020-06-07-correlation-parameter-mem/ranef_2.png differ diff --git a/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/figure-html5/unnamed-chunk-4-1.png b/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/figure-html5/unnamed-chunk-4-1.png new file mode 100644 index 00000000..b65462d5 Binary files /dev/null and b/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/figure-html5/unnamed-chunk-4-1.png differ diff --git a/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-06-25-indexing-tip-for-spacyr/2020-06-25-indexing-tip-for-spacyr_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-06-25-indexing-tip-for-spacyr/index.html b/docs/posts/2020-06-25-indexing-tip-for-spacyr/index.html new file mode 100644 index 00000000..f7587b6e --- /dev/null +++ b/docs/posts/2020-06-25-indexing-tip-for-spacyr/index.html @@ -0,0 +1,4264 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Indexing tip for {spacyr} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Indexing tip for {spacyr}

    + +
    + data wrangling + NLP + spacyr +
    + +

    Speeding up the analysis of dependency relations.

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    06-25-2020 +
    + +
    +
    + +
    +

    The {spacyr} package is an R wrapper for Python’s spaCy package, powered by {reticulate}. Although it’s been around for over 3 years, it doesn’t seem to have really been picked up by R users.1 I actually think this makes sense since what makes spaCy so great is its object-oriented approach to NLP (which Python is good at). But perhaps more importantly, a good portion of data wrangling in spaCy is reducible to operating on vectors of such tokens, and I think that comes pretty naturally for R users with a functional programming background.2 So my guess is that since spaCy is accessible to R users, {spacyr} isn’t that widely used.

    +

    But with that said, I like to make my workflow as R-centered as possible and I think there’s still value in {spacyr} at least for very simple, exploratory analysis of text. The results being returned in a tidy format is a huge plus, and it doesn’t seem to sacrifice much speed.

    +

    There’s a good guide to using {spacyr} in the CRAN vignette which covers pretty much everything you need to know if you’re already familiar with spaCy (and if you aren’t, there’s a great cheatsheet from DataCamp).

    +

    Everything I just said above was just a whole lot of background information. What I really want to do here to contribute to the discussion around {spacyr} by sharing a tip for analyzing dependency relations from the output of spacy_parse(), which is {spacyr}’s main function that combines both the model-loading and text-processing stages of spaCy.

    +
    + +
    +

    For illustration, I’ll be using the 8 State of the Union addresses by President Barack Obama from 2009-2016, which comes from the {sotu} package.

    +
    +
    +
    library(sotu)
    +doc <- tail(sotu::sotu_text, 8)
    +
    +# First 100 characters of each speech
    +strtrim(doc, 100)
    +
    +
    +
      [1] "Madam Speaker, Mr. Vice President, Members of Congress, the First Lady of the United States--she's a"
    +  [2] "Madam Speaker, Vice President Biden, Members of Congress, distinguished guests, and fellow Americans"
    +  [3] "Mr. Speaker, Mr. Vice President, Members of Congress, distinguished guests, and fellow Americans: To"
    +  [4] "Mr. Speaker, Mr. Vice President, Members of Congress, distinguished guests, and fellow Americans: La"
    +  [5] "Please, everybody, have a seat. Mr. Speaker, Mr. Vice President, Members of Congress, fellow America"
    +  [6] "The President. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: Today in A"
    +  [7] "The President. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: We are 15 "
    +  [8] "Thank you. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: Tonight marks "
    +
    +

    We can pass this document to spacy_parse() to get back a dataframe of tokens and their attributes in tidy format, where each row (observation) is a token.3

    +
    +
    +
    parsed <- spacy_parse(doc, dep = TRUE, entity = FALSE)
    +
    +head(parsed, 10)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token + +lemma + +pos + +head_token_id + +dep_rel +
    +text1 + +1 + +1 + +Madam + +Madam + +PROPN + +2 + +compound +
    +text1 + +1 + +2 + +Speaker + +Speaker + +PROPN + +2 + +ROOT +
    +text1 + +1 + +3 + +, + +, + +PUNCT + +2 + +punct +
    +text1 + +1 + +4 + +Mr.  + +Mr.  + +PROPN + +6 + +compound +
    +text1 + +1 + +5 + +Vice + +Vice + +PROPN + +6 + +compound +
    +text1 + +1 + +6 + +President + +President + +PROPN + +2 + +appos +
    +text1 + +1 + +7 + +, + +, + +PUNCT + +6 + +punct +
    +text1 + +1 + +8 + +Members + +Members + +PROPN + +6 + +appos +
    +text1 + +1 + +9 + +of + +of + +ADP + +8 + +prep +
    +text1 + +1 + +10 + +Congress + +Congress + +PROPN + +9 + +pobj +
    +
    +

    This output format is great for plotting in R with the familiar packages. For example, we can make a bar plot of top adjectives used by Obama in his SOTU addresses with minimal changes to the output.

    +
    +
    +
    # Load tidytext package for stopwords
    +library(tidytext)
    +
    +parsed %>%
    +  filter(pos == "ADJ",
    +         str_detect(lemma, "^[:alpha:].*[:alpha:]$"),
    +         !lemma %in% tidytext::stop_words$word) %>%
    +  count(lemma) %>% 
    +  mutate(lemma = fct_reorder(str_to_title(lemma), n)) %>%
    +  top_n(15) %>% 
    +  ggplot(aes(lemma, n)) +
    +  geom_col() +
    +  coord_flip() +
    +  labs(title = "Top 15 Adjectives from President Obama's SOTU Addresses",
    +       x = "Adjective", y = "Count") +
    +  theme_classic()
    +
    +
    +

    +
    +

    The Challenge

    +

    But what if we want to dig a little deeper in our analysis of adjectives? What if, for example, we were interested in the adjectives that were used to describe “America”

    +

    Because we set dep = TRUE when we called spacy_parse() earlier, we have information about dependencies in the dep_rel column and the head_token_id column. To be more precise, dep_rel is the .dep_ attribute from spaCy and head_token_id is the row index of the head token (.head attribute from spaCy) that is unique to the spacy_parse() output.

    +

    For example, let’s look at the the 298th sentence from Obama’s third SOTU address:

    +
    +
    +
    example_sentence <- parsed %>% 
    +  filter(doc_id == "text3", sentence_id == 298) %>% 
    +  pull(token) %>% 
    +  str_c(collapse = " ") %>% 
    +  str_remove_all(" (?=[:punct:])")
    +
    +example_sentence
    +
    +
    +
      [1] "Now, we've made great strides over the last 2 years in using technology and getting rid of waste."
    +
    +

    And here’s a visualization of the dependency parse made with displaCy. Sadly, displaCy is not a part of {spacyr}, so I’m just calling Python here using {reticulate}.

    +
    +
    ######## Python Code ########
    +import spacy
    +from spacy import displacy
    +nlp = spacy.load('en_core_web_sm')
    +example_parsed = nlp(r.example_sentence)
    +
    +
    +
    displacy.render(example_parsed, style = "dep")
    +
    + +
    +
    +

    Now,ADVwePRON'veAUXmadeVERBgreatADJstridesNOUNoverADPtheDETlastADJ2NUMyearsNOUNinADPusingVERBtechnologyNOUNandCCONJgettingVERBridVERBofADPwaste.NOUNadvmodnsubjauxamoddobjprepdetamodnummodpobjpreppcompdobjccauxpassconjpreppobj

    +
    +
    +

     

    +

    Basically, the task here is to find words like “competitive” in the example sentence above where the token is an adjective and its head is the word “America”, but it turns out harder than it seems.

    +

    The output of spacy_parse is set up such that every sentence stands on their own. More specifically speaking, the indices stored in token_id and head_token_id are local indices relative to each sentence.4 So while there are a total of 62791 tokens in parsed, the max token_id is 99, which is the index of the last token in the longest sentence.

    +

    A strictly tidyverse approach (which has become a sort of a tunnel-vision for me) would be to split parsed by sentence and map a filter function to each sentence. There are two ways of going about this and both are pretty slow.

    +

    The first way is to explicitly split the dataframe into a list of dataframes at the sentence level then map the filter function, using group_split() then map_df():

    +
    +
    +
    tic <- Sys.time()
    +
    +parsed %>%
    +    group_split(doc_id, sentence_id, .drop = FALSE) %>%
    +    map_df(~filter(., pos == "ADJ", slice(.x, head_token_id)$lemma == "America"))
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token + +lemma + +pos + +head_token_id + +dep_rel +
    +text3 + +302 + +33 + +competitive + +competitive + +ADJ + +34 + +amod +
    +text4 + +231 + +33 + +rural + +rural + +ADJ + +34 + +amod +
    +text5 + +245 + +2 + +stronger + +strong + +ADJ + +3 + +amod +
    +text6 + +340 + +18 + +strong + +strong + +ADJ + +21 + +amod +
    +text7 + +317 + +23 + +liberal + +liberal + +ADJ + +24 + +amod +
    +text7 + +317 + +27 + +conservative + +conservative + +ADJ + +28 + +amod +
    +
    +
    Sys.time() - tic
    +
    +
    +
      Time difference of 12.0861 secs
    +
    +

    The second way is to implicitly declare a grouping by sentence and then map the filter function, using group_by() then group_map():

    +
    +
    +
    tic <- Sys.time()
    +
    +parsed %>%
    +  group_by(doc_id, sentence_id) %>%
    +  group_map(~filter(., pos == "ADJ", slice(.x, head_token_id)$lemma == "America"), .keep = TRUE) %>%
    +  bind_rows()
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token + +lemma + +pos + +head_token_id + +dep_rel +
    +text3 + +302 + +33 + +competitive + +competitive + +ADJ + +34 + +amod +
    +text4 + +231 + +33 + +rural + +rural + +ADJ + +34 + +amod +
    +text5 + +245 + +2 + +stronger + +strong + +ADJ + +3 + +amod +
    +text6 + +340 + +18 + +strong + +strong + +ADJ + +21 + +amod +
    +text7 + +317 + +23 + +liberal + +liberal + +ADJ + +24 + +amod +
    +text7 + +317 + +27 + +conservative + +conservative + +ADJ + +28 + +amod +
    +
    +
    Sys.time() - tic
    +
    +
    +
      Time difference of 11.63191 secs
    +
    +

    Both ways give us the result we want, but it’s significantly slower than what we could quickly and easily do in Python.

    +
    +
    ######## Python Code ########
    +doc = nlp(' '.join(r.doc))
    +
    +import time
    +tic = time.time()
    +
    +[token.text for token in doc if token.pos_ == "ADJ" and token.head.lemma_ == "America"]
    +
      ['competitive', 'rural', 'stronger', 'strong', 'liberal', 'conservative']
    +
    time.time() - tic
    +
      0.04711294174194336
    +
    +

    A Work-around

    +

    What would really help here is if we had global indices for tokens and head tokens, so that we can directly index a head from a token without going through the trouble of figuring out how sentences are organized in the dataframe.

    +

    So here’s my take on doing this:

    +
    +
    +
    # Calculate global indices from local indices
    +global_index <- parsed %>% 
    +  group_by(doc_id, sentence_id) %>% 
    +  # add token counts for each sentence
    +  add_count() %>% 
    +  ungroup() %>% 
    +  select(doc_id, sentence_id, n) %>% 
    +  distinct() %>%
    +  # take the cumulative sum and shift 1 to the right (fill first index with 0)
    +  mutate(n = c(0, cumsum(n)[1:n()-1]))
    +
    +# Clean the output
    +parsed2 <- parsed %>% 
    +  inner_join(global_index, by = c("doc_id", "sentence_id")) %>% 
    +  mutate(token_id_global = token_id + n,
    +         head_token_id_global = head_token_id + n) %>% 
    +  relocate(token_id_global, .after = token_id) %>% 
    +  relocate(head_token_id_global, .after = head_token_id) %>% 
    +  select(-n)
    +
    +
    +
    +

    This adds two colums - token_id_global and head_token_id_global - that stores indices that range over the entire dataframe. Here’s a sample of the new dataframe to demonstrate:

    +
    +
    +
    sample_n(parsed2, 10)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token_id_global + +token + +lemma + +pos + +head_token_id + +head_token_id_global + +dep_rel +
    +text7 + +37 + +11 + +48388 + +to + +to + +ADP + +10 + +48387 + +dative +
    +text3 + +154 + +3 + +18253 + +the + +the + +DET + +5 + +18255 + +det +
    +text1 + +44 + +2 + +1036 + +of + +of + +ADP + +1 + +1035 + +pcomp +
    +text8 + +17 + +6 + +56007 + +to + +to + +ADP + +5 + +56006 + +prep +
    +text5 + +316 + +3 + +38631 + +this + +this + +DET + +4 + +38632 + +nsubj +
    +text6 + +340 + +15 + +46579 + +then + +then + +ADV + +23 + +46587 + +advmod +
    +text4 + +162 + +7 + +26488 + + + +SPACE + +6 + +26487 + +
    +text6 + +87 + +13 + +41466 + +to + +to + +PART + +14 + +41467 + +aux +
    +text8 + +260 + +17 + +60517 + +positioned + +position + +VERB + +9 + +60509 + +conj +
    +text8 + +281 + +2 + +60856 + +is + +be + +AUX + +11 + +60865 + +ccomp +
    +
    +

    And since this process isn’t destructive, we actually don’t need to assign the output to a new object. This is great because we can flexibly incorporate it into the pipeline workflow.

    +

    Here is my solution wrapped in a function:5

    +
    +
    +
    add_global_index <- function(spacy_parsed) {
    +  
    +  global_index <- spacy_parsed %>% 
    +    group_by(doc_id, sentence_id) %>% 
    +    add_count() %>% 
    +    ungroup() %>% 
    +    select(doc_id, sentence_id, n) %>% 
    +    distinct() %>%
    +    mutate(n = c(0, cumsum(n)[1:n()-1]))
    +  
    +  spacy_parsed %>% 
    +    inner_join(global_index, by = c("doc_id", "sentence_id")) %>% 
    +    mutate(token_id_global = token_id + n,
    +           head_token_id_global = head_token_id + n) %>% 
    +    relocate(token_id_global, .after = token_id) %>% 
    +    relocate(head_token_id_global, .after = head_token_id) %>% 
    +    select(-n)
    +  
    +}
    +
    +
    +
    +

    In action:

    +
    +
    +
    # Find adjectives describing "America"
    +parsed %>% 
    +  add_global_index() %>% 
    +  filter(pos == "ADJ", slice(., head_token_id_global)$lemma == "America")
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token_id_global + +token + +lemma + +pos + +head_token_id + +head_token_id_global + +dep_rel +
    +text3 + +302 + +33 + +21359 + +competitive + +competitive + +ADJ + +34 + +21360 + +amod +
    +text4 + +231 + +33 + +27772 + +rural + +rural + +ADJ + +34 + +27773 + +amod +
    +text5 + +245 + +2 + +36825 + +stronger + +strong + +ADJ + +3 + +36826 + +amod +
    +text6 + +340 + +18 + +46582 + +strong + +strong + +ADJ + +21 + +46585 + +amod +
    +text7 + +317 + +23 + +54054 + +liberal + +liberal + +ADJ + +24 + +54055 + +amod +
    +text7 + +317 + +27 + +54058 + +conservative + +conservative + +ADJ + +28 + +54059 + +amod +
    +
    +
    +
    +
    # Find adjectives describing "America" inside a prepositional phrase
    +parsed %>% 
    +  add_global_index() %>% 
    +  filter(pos == "ADJ", slice(., head_token_id_global)$lemma == "America",
    +         slice(., slice(., head_token_id_global)$head_token_id_global)$dep_rel == "prep")
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +doc_id + +sentence_id + +token_id + +token_id_global + +token + +lemma + +pos + +head_token_id + +head_token_id_global + +dep_rel +
    +text3 + +302 + +33 + +21359 + +competitive + +competitive + +ADJ + +34 + +21360 + +amod +
    +text4 + +231 + +33 + +27772 + +rural + +rural + +ADJ + +34 + +27773 + +amod +
    +
    +

    Performance:

    +
    +
    +
    test <- function(){
    +  parsed %>% 
    +    add_global_index() %>% 
    +    filter(pos == "ADJ", slice(., head_token_id_global)$lemma == "America")
    +}
    +
    +print(microbenchmark::microbenchmark(test(), unit = "s"))
    +
    +
    +
      Unit: seconds
    +     expr       min         lq      mean  median        uq       max neval
    +   test() 0.0909179 0.09831835 0.1109029 0.10356 0.1122529 0.3129214   100
    +
    +

    Much better!

    +

     

    +

    Session Info

    +
    +
      R version 4.0.3 (2020-10-10)
    +  Platform: x86_64-w64-mingw32/x64 (64-bit)
    +  Running under: Windows 10 x64 (build 18363)
    +  
    +  Matrix products: default
    +  
    +  locale:
    +  [1] LC_COLLATE=English_United States.1252 
    +  [2] LC_CTYPE=English_United States.1252   
    +  [3] LC_MONETARY=English_United States.1252
    +  [4] LC_NUMERIC=C                          
    +  [5] LC_TIME=English_United States.1252    
    +  
    +  attached base packages:
    +  [1] stats     graphics  grDevices datasets  utils     methods   base     
    +  
    +  other attached packages:
    +   [1] tidytext_0.2.6  sotu_1.0.2      reticulate_1.18 stringr_1.4.0  
    +   [5] spacyr_1.2.1    forcats_0.5.0   ggplot2_3.3.2   purrr_0.3.4    
    +   [9] dplyr_1.0.2     printr_0.1     
    +  
    +  loaded via a namespace (and not attached):
    +   [1] Rcpp_1.0.5           highr_0.8            pillar_1.4.6        
    +   [4] compiler_4.0.3       tokenizers_0.2.1     tools_4.0.3         
    +   [7] digest_0.6.26        downlit_0.2.0        jsonlite_1.7.1      
    +  [10] lattice_0.20-41      evaluate_0.14        lifecycle_0.2.0     
    +  [13] tibble_3.0.4         gtable_0.3.0         pkgconfig_2.0.3     
    +  [16] rlang_0.4.8          Matrix_1.2-18        rstudioapi_0.11     
    +  [19] microbenchmark_1.4-7 distill_1.0          yaml_2.2.1          
    +  [22] xfun_0.18            janeaustenr_0.1.5    withr_2.2.0         
    +  [25] knitr_1.30           rappdirs_0.3.1       generics_0.0.2      
    +  [28] vctrs_0.3.4          grid_4.0.3           tidyselect_1.1.0    
    +  [31] data.table_1.13.2    glue_1.4.2           R6_2.4.1            
    +  [34] fansi_0.4.1          rmarkdown_2.5        farver_2.0.3        
    +  [37] magrittr_1.5.0.9000  SnowballC_0.7.0      prismatic_0.2.0     
    +  [40] scales_1.1.1         ellipsis_0.3.1       htmltools_0.5.0     
    +  [43] gt_0.2.2             colorspace_1.4-1     renv_0.12.0         
    +  [46] labeling_0.4.2       stringi_1.5.3        munsell_0.5.0       
    +  [49] crayon_1.3.4
    +
    +
    +
    +
    +
      +
    1. There are less than 30 posts about it on StackOverflow, for example.↩︎

    2. +
    3. I personally found it very easy to pick up vector comprehension in Python after working with purrr::map, for example.↩︎

    4. +
    5. The argument entity = FALSE is the same as disable = ['ner'] in spacy.load() in Python. I did this to save computation time.↩︎

    6. +
    7. This format is shared across other NLP packages in R based on spacCy, like {cleanNLP}↩︎

    8. +
    9. This would need to be tweaked a bit if you want to use it for the output of {cleanNLP} because the column for the local index of token heads, tid_source, is 0 when the token is the ROOT, as opposed to its own token index, which is the case in {spacyr}. You could add something like mutate(tid_source = ifelse(tid_source == 0, tid, tid_source) to the beginning of the pipeline to address this.↩︎

    10. +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-06-25-indexing-tip-for-spacyr/preview.png b/docs/posts/2020-06-25-indexing-tip-for-spacyr/preview.png new file mode 100644 index 00000000..c20b43a6 Binary files /dev/null and b/docs/posts/2020-06-25-indexing-tip-for-spacyr/preview.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-11-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-11-1.png new file mode 100644 index 00000000..6bd6c005 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-11-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-12-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-12-1.png new file mode 100644 index 00000000..725e79e4 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-12-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-3-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-3-1.png new file mode 100644 index 00000000..07143101 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-3-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..cb6586e4 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..c5aa2d3a Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..eab18f0e Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-8-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-8-1.png new file mode 100644 index 00000000..9e2e8805 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-8-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..2e2530b0 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/highcharter_pokemon.png b/docs/posts/2020-06-30-treemap-with-ggplot/highcharter_pokemon.png new file mode 100644 index 00000000..e061b986 Binary files /dev/null and b/docs/posts/2020-06-30-treemap-with-ggplot/highcharter_pokemon.png differ diff --git a/docs/posts/2020-06-30-treemap-with-ggplot/index.html b/docs/posts/2020-06-30-treemap-with-ggplot/index.html new file mode 100644 index 00000000..39ee9fa2 --- /dev/null +++ b/docs/posts/2020-06-30-treemap-with-ggplot/index.html @@ -0,0 +1,3209 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Plotting treemaps with {treemap} and {ggplot2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Plotting treemaps with {treemap} and {ggplot2}

    + +
    + data visualization + treemap + ggplot2 + tutorial +
    + +

    Using underlying plot data for maximum customization

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    06-30-2020 +
    + +
    +
    + +
    +

    To steal the definition from Wikipedia, a treemap is used for “displaying hierarchical data using nested figures, usually rectangles.” There are lots of ways to make one in R, but I didn’t find any one existing solution appealing.

    +

    For illustration, let’s take the pokemon dataset from {highcharter} and plot a treemap with it using different methods.

    +
    + +
    +
    +
    +
    data("pokemon", package = "highcharter")
    +
    +# Cleaning up data for a treemap
    +data <- pokemon %>% 
    +  select(pokemon, type_1, type_2, color_f) %>%
    +  mutate(type_2 = ifelse(is.na(type_2), paste("only", type_1), type_2)) %>% 
    +  group_by(type_1, type_2, color_f) %>% 
    +  count(type_1, type_2) %>% 
    +  ungroup()
    +
    +head(data, 5)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +type_1 + +type_2 + +color_f + +n +
    +bug + +electric + +#BBBD23 + +2 +
    +bug + +fighting + +#AD9721 + +1 +
    +bug + +fire + +#B9AA23 + +2 +
    +bug + +flying + +#A8AE52 + +13 +
    +bug + +ghost + +#9AA03D + +1 +
    +
    +

     

    +

    1. {treemap}

    +

    Here’s a plot made from the {treemap} package:

    +
    +
    +
    library(treemap)
    +
    +treemap(dtf = data,
    +        index = c("type_1", "type_2"),
    +        vSize = "n",
    +        vColor = "type_1")
    +
    +
    +

    +
    +

    It actually doesn’t look too bad, but this package hasn’t been updated for 3 years and there aren’t a lot of options for customization. For the options that do exist, they’re a big list of additional arguments to the main workhorse function, treemap(), which feels a bit restrictive if you’re used to {ggplot}’s modular and layered grammar. So while it’s very simple to use, I’d probably use it only for exploring the data for myself.

    +

     

    +

    2. {highcharter}

    +

    All the way on the other side of this ease<—>customizability spectrum is {highcharter} which is arguably the most powerful data visualization package in R.

    +

    With highcharter, you can turn the previous graph into the following:

    +

    +

    This looks much better, and it’s even interactive (although this particular one isn’t because I just copy pasted the image from this blog post from 2018). I’d use {highcharter} except that there isn’t a great documentation on plotting treemaps, and it definitely doesn’t help that {highcharter} has a pretty steep learning curve, even if you have a lot of experience with {ggplot2}.

    +

    The main problem I ran into is that the function hc_add_series_treemap() that was used to create the above graph is now depreciated. It redirects you to use hctreemap() which itself is also depreciated. That finally redirects you to use hctreemap2() which is pretty sparse in documentation and use-cases, and overall not very transparent IMO.

    +

     

    +

    3. {treemapify}

    +

    {treemapify} is a ggplot solution to plotting treemaps.

    +

    Here’s a plot of the pokemon dataset, adopting the example code from the vignette. Since it follows the layered grammar of ggplot, I figured I’d show what each of the four layers outlined in the code does:

    +
    +
    +
    library(treemapify)
    +
    +ggplot(data, aes(area = n, fill = color_f, label = type_2,
    +                subgroup = type_1)) +
    +  # 1. Draw type_2 borders and fill colors
    +  geom_treemap() +
    +  # 2. Draw type_1 borders
    +  geom_treemap_subgroup_border() +
    +  # 3. Print type_1 text
    +  geom_treemap_subgroup_text(place = "centre", grow = T, alpha = 0.5, colour = "black",
    +                             fontface = "italic", min.size = 0) +
    +  # 4. Print type_2 text
    +  geom_treemap_text(colour = "white", place = "topleft", reflow = T) +
    +  theme(legend.position = 0)
    +
    +
    +
    +

    geom_treemap() draws type_2 borders and fill colors

    +
    +

    +
    +

    geom_treemap_subgroup_border() draws type_1 borders

    +
    +

    +
    +

    geom_treemap_subgroup_text() prints type_1 text

    +
    +

    +
    +

    geom_treemap_text() prints type_2 text

    +
    +

    +
    +

    I find this the most appealing out of the three options and I do recommend this package, but I’m personally a bit hesistant to use it for three reasons:

    +
      +
    1. I don’t want to learn a whole ’nother family of geom_*s just to plot treemaps.

    2. +
    3. Some of the ggplot “add-ons” that I like don’t really transfer over. For example, I can’t use geom_text_repel() from {ggrepel} because I have to use {treemapify}’s own text geoms like geom_treemap_subgroup_text() and geom_treemap_text().

    4. +
    5. Customization options are kind of a mouthful, and I’ve yet to see a nice-looking treemap that was plotted using this package. There are a couple example treemaps in the vignette but none of them look particularly good. An independently produced example here doesn’t look super great either.

    6. +
    +

     

    +

    A Mixed (Hack-ish?) Solution

    +

    Basically, I’m very lazy and I want to avoid learning any new packages or functions as much as possible.

    +

    I’ve come up with a very simple solution to my self-created problem, which is to draw treemaps using geom_rect() with a little help from the {treemap} package introduced earlier.

    +

    So apparently, there’s a cool feature in treemap::treemap() where you can extract the plotting data.

    +

    You can do this by pulling the tm object from the plot function side-effect, and the underlying dataframe used for plotting looks like this.1:

    +
    +
    +
    tm <- treemap(
    +  dtf = data,
    +  index = c("type_1", "type_2"),
    +  vSize = "n",
    +  vColor = "color_f",
    +  type = 'color' # {treemap}'s equivalent of scale_fill_identity()
    +)
    +
    +
    +
    +
    head(tm$tm)
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +type_1 + +type_2 + +vSize + +vColor + +stdErr + +vColorValue + +level + +x0 + +y0 + +w + +h + +color +
    +bug + +electric + +2 + +#BBBD23 + +2 + +NA + +2 + +0.4556639 + +0.3501299 + +0.0319174 + +0.0872727 + +#BBBD23 +
    +bug + +fighting + +1 + +#AD9721 + +1 + +NA + +2 + +0.4556639 + +0.3064935 + +0.0319174 + +0.0436364 + +#AD9721 +
    +bug + +fire + +2 + +#B9AA23 + +2 + +NA + +2 + +0.4875812 + +0.3501299 + +0.0319174 + +0.0872727 + +#B9AA23 +
    +bug + +flying + +13 + +#A8AE52 + +13 + +NA + +2 + +0.2757660 + +0.2628571 + +0.1160631 + +0.1560000 + +#A8AE52 +
    +bug + +ghost + +1 + +#9AA03D + +1 + +NA + +2 + +0.4556639 + +0.2628571 + +0.0319174 + +0.0436364 + +#9AA03D +
    +bug + +grass + +6 + +#9CBB2B + +6 + +NA + +2 + +0.4744388 + +0.4374026 + +0.0450598 + +0.1854545 + +#9CBB2B +
    +
    +

    We can simply use this data to recreate the treemap that was made with {treemapify} - except this time we have more flexibility!

    +

    First, we do some data cleaning:

    +
    +
    +
    tm_plot_data <- tm$tm %>% 
    +  # calculate end coordinates with height and width
    +  mutate(x1 = x0 + w,
    +         y1 = y0 + h) %>% 
    +  # get center coordinates for labels
    +  mutate(x = (x0+x1)/2,
    +         y = (y0+y1)/2) %>% 
    +  # mark primary groupings and set boundary thickness
    +  mutate(primary_group = ifelse(is.na(type_2), 1.2, .5)) %>% 
    +  # remove colors from primary groupings (since secondary is already colored)
    +  mutate(color = ifelse(is.na(type_2), NA, color))
    +
    +
    +
    +

    Then we plot. It looks like I can recreate a lot of it with a little help from the {ggfittext} package that was in the source code2:

    +
    +
    +
    ggplot(tm_plot_data, aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1)) + 
    +  # add fill and borders for groups and subgroups
    +  geom_rect(aes(fill = color, size = primary_group),
    +            show.legend = FALSE, color = "black", alpha = .3) +
    +  scale_fill_identity() +
    +  # set thicker lines for group borders
    +  scale_size(range = range(tm_plot_data$primary_group)) +
    +  # add labels
    +  ggfittext::geom_fit_text(aes(label = type_2), min.size = 1) +
    +  # options
    +  scale_x_continuous(expand = c(0, 0)) +
    +  scale_y_continuous(expand = c(0, 0)) +
    +  theme_void()
    +
    +
    +

    +
    +

    Now, I can be a lot more flexible with my customizations.

    +

    For example, let’s say I wanted to isolate and emphasize the secondary types that have unique type-combinations with steel, AND also provide the name of the corresponding pokemon.

    +

    I can do this by using geom_text_repel() for a subset of the labels while keeping the same geom_fit_text() setting for the rest of the labels.

    +
    +
    +
    tm_plot_data %>% 
    +  ggplot(aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1)) + 
    +  geom_rect(aes(fill = color, size = primary_group),
    +            show.legend = FALSE, color = "black", alpha = .3) +
    +  scale_fill_identity() +
    +  scale_size(range = range(tm_plot_data$primary_group)) +
    +  ggfittext::geom_fit_text(data = filter(tm_plot_data, type_1 != "steel" | vSize > 1),
    +                           aes(label = type_2), min.size = 1) +
    +  # pick out observations of interest and annotate with geom_text_repel
    +  ggrepel::geom_text_repel(
    +    data = filter(tm_plot_data, vSize == 1, type_1 == "steel") %>% 
    +      inner_join(pokemon, by = c("type_1", "type_2")),
    +    aes(x = x, y = y, label = glue::glue("{type_2} ({pokemon})")),
    +    color = "black", xlim = c(1.02, NA), size = 4,
    +    direction = "y", vjust = .5, force = 3
    +  ) +
    +  # expand x-axis limits to make room for test annotations
    +  scale_x_continuous(limits = c(0, 1.2), expand = c(0, 0)) +
    +  scale_y_continuous(expand = c(0, 0)) +
    +  theme_void()
    +
    +
    +

    +
    +

    And that’s our final product! This would’ve been pretty difficult to do with any of the three options I reviewed at the top!

    +

    tl;dr - Use treemap() from the {treemap} package to get positions for geom_rect()s and you’re 90% of the way there to plotting a treemap! Apply your favorite styles (especially _text() geoms) from the {ggplot2} ecosystem for finishing touches!

    +

     

    +

    Session Info

    +
    +
    +
    sessionInfo()
    +
    +
    +
      R version 4.0.3 (2020-10-10)
    +  Platform: x86_64-w64-mingw32/x64 (64-bit)
    +  Running under: Windows 10 x64 (build 18363)
    +  
    +  Matrix products: default
    +  
    +  locale:
    +  [1] LC_COLLATE=English_United States.1252 
    +  [2] LC_CTYPE=English_United States.1252   
    +  [3] LC_MONETARY=English_United States.1252
    +  [4] LC_NUMERIC=C                          
    +  [5] LC_TIME=English_United States.1252    
    +  
    +  attached base packages:
    +  [1] stats     graphics  grDevices datasets  utils     methods   base     
    +  
    +  other attached packages:
    +   [1] treemapify_2.5.3 treemap_2.4-2    printr_0.1       forcats_0.5.0   
    +   [5] stringr_1.4.0    dplyr_1.0.2      purrr_0.3.4      readr_1.4.0     
    +   [9] tidyr_1.1.2      tibble_3.0.4     ggplot2_3.3.2    tidyverse_1.3.0 
    +  
    +  loaded via a namespace (and not attached):
    +   [1] httr_1.4.2          jsonlite_1.7.1      modelr_0.1.8       
    +   [4] shiny_1.5.0         assertthat_0.2.1    highr_0.8          
    +   [7] blob_1.2.1          renv_0.12.0         cellranger_1.1.0   
    +  [10] ggrepel_0.8.2       yaml_2.2.1          pillar_1.4.6       
    +  [13] backports_1.1.10    glue_1.4.2          digest_0.6.26      
    +  [16] RColorBrewer_1.1-2  promises_1.1.1      rvest_0.3.6        
    +  [19] colorspace_1.4-1    htmltools_0.5.0     httpuv_1.5.4       
    +  [22] pkgconfig_2.0.3     broom_0.7.2         haven_2.3.1        
    +  [25] xtable_1.8-4        scales_1.1.1        later_1.1.0.1      
    +  [28] distill_1.0.1       downlit_0.2.0       generics_0.0.2     
    +  [31] farver_2.0.3        ellipsis_0.3.1      withr_2.2.0        
    +  [34] cli_2.1.0           magrittr_1.5.0.9000 crayon_1.3.4       
    +  [37] readxl_1.3.1        mime_0.9            evaluate_0.14      
    +  [40] fs_1.5.0            fansi_0.4.1         xml2_1.3.2         
    +  [43] tools_4.0.3         data.table_1.13.2   hms_0.5.3          
    +  [46] lifecycle_0.2.0     gridBase_0.4-7      munsell_0.5.0      
    +  [49] reprex_0.3.0        compiler_4.0.3      rlang_0.4.8        
    +  [52] grid_4.0.3          gt_0.2.2            rstudioapi_0.11    
    +  [55] igraph_1.2.6        labeling_0.4.2      rmarkdown_2.5      
    +  [58] gtable_0.3.0        DBI_1.1.0           R6_2.4.1           
    +  [61] lubridate_1.7.9     knitr_1.30          fastmap_1.0.1      
    +  [64] prismatic_0.2.0     stringi_1.5.3       Rcpp_1.0.5         
    +  [67] vctrs_0.3.4         ggfittext_0.9.0     dbplyr_1.4.4       
    +  [70] tidyselect_1.1.0    xfun_0.18
    +
    +
    +
    +
    +
      +
    1. You might get a warning referencing something about data.table here. No worries if this happens. The outdated {treemap} source code is built on {data.table} and contains a deprecated argument.↩︎

    2. +
    3. I highly recommend checking {ggfittext} out! Here’s the github repo. Also, this is more of a note to myself but I had some trouble getting this to work at first because the min.size argument defaults to 4, meaning that all fitted text smaller than size 4 are simply not plotted (so I couldn’t get geom_fit_text() to print anything in my treemap at first). You can compare and see the threshold by looking at the geom_text_repel() texts in my second example which also has a size of 4.↩︎

    4. +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-3-1.png b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-3-1.png new file mode 100644 index 00000000..ddc07bb4 Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-3-1.png differ diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-4-1.png b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-4-1.png new file mode 100644 index 00000000..57ae7ce1 Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-4-1.png differ diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..e7de1e2a Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..b0b5f541 Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..7468c2a5 Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-07-13-geom-paired-raincloud/2020-07-13-geom-paired-raincloud_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/index.html b/docs/posts/2020-07-13-geom-paired-raincloud/index.html new file mode 100644 index 00000000..3b063fa4 --- /dev/null +++ b/docs/posts/2020-07-13-geom-paired-raincloud/index.html @@ -0,0 +1,2792 @@ + + + + + + + + + + + + + + + + + + + +June Choe: geom_paired_raincloud() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    geom_paired_raincloud()

    + +
    + data visualization + ggplot2 +
    + +

    A {ggplot2} geom for visualizing change in distribution between two conditions.

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    07-13-2020 +
    + +
    +
    + +
    +

    Raincloud Plots

    +
    + +
    +

    Geoms for rainplots (a.k.a. split violin plots) already exist, but you might have a very special case where you have pairs of rainplots and you want to track the change in individual datapoints between the rainplot distributions.

    +

    For example, say you want to track the height of a plant species across two timepoints and you want to communicate three information:

    +
      +
    1. The change in the distribution of plant heights between timepoints.

    2. +
    3. The individual variation in height (“intercept”).

    4. +
    5. The individual variation in change of height between timepoints (“slope”).

    6. +
    +

    And the data looks like this:

    +
    +
    +
    set.seed(1234)
    +plants <- tibble(Species = "Dwarf",
    +                 Plant = rep(factor(1:100), 2),
    +                 Timepoint = rep(c("First", "Second"), each = 100),
    +                 Height = c(rnorm(100, 10, 5), rnorm(100, 20, 8)))
    +
    +plants %>% 
    +  group_by(Timepoint) %>% 
    +  summarize(across(Height, list(mean = mean, sd = sd), .names = "{col}_{fn}"))
    +
    +
    +
      # A tibble: 2 x 3
    +    Timepoint Height_mean Height_sd
    +    <chr>           <dbl>     <dbl>
    +  1 First            9.22      5.02
    +  2 Second          20.3       8.26
    +
    +

    You can use geom_violhalf() from the {see} package to do this:

    +
    +
    +
    library(see)
    +ggplot(plants, aes(Timepoint, Height, fill = Timepoint)) +
    +  geom_violinhalf() +
    +  geom_point(aes(group = Plant),
    +             position = position_nudge(-.05),
    +             alpha = 0.5, shape = 16) +
    +  geom_line(aes(group = Plant),
    +            position = position_nudge(-.05))
    +
    +
    +

    +
    +

    But it’d look better if the lines don’t cross over the raincloud for the first timepoint.

    +

    geom_paired_raincloud() automatically flips the first raincloud for you! You do get a warining that there are overlapping points, but that’s because the x-axis is categorical and {ggplot2} thinks that flipping the raincloud intrudes into a different category. AFAIK you don’t lose any data despite this warning, but you should double check to be sure.

    +
    +
    +
    devtools::source_url("https://raw.githubusercontent.com/yjunechoe/geom_paired_raincloud/master/geom_paired_raincloud.R")
    +
    +ggplot(plants, aes(Timepoint, Height, fill = Timepoint)) +
    +  geom_paired_raincloud()
    +
    +
    +
      Warning: position_dodge requires non-overlapping x intervals
    +

    +
    +

    We can add individual points and lines onto this plot in a similar way, except you need to use a 2-length vector for position_dodge().

    +
    +
    +
    plants %>% 
    +  # arrange by individual plant
    +  arrange(Plant) %>% 
    +  ggplot(aes(Timepoint, Height, fill = Timepoint)) +
    +  geom_paired_raincloud() +
    +  geom_point(aes(group = Plant),
    +             position = position_nudge(c(.05, -.05)),
    +             alpha = 0.5, shape = 16,
    +             show.legend = FALSE) +
    +  geom_line(aes(group = Plant),
    +            position = position_nudge(c(.05, -.05)))
    +
    +
    +

    +
    + +

    geom_paired_raincloud works as long as the grouping is of length two (i.e., as long as you’re comparing distribution between two levels).

    +

    Let’s modify the plants dataset to include another species of plant:

    +
    +
    +
    plants2 <- plants %>% 
    +  bind_rows(
    +    tibble(Species = "Giant",
    +           Plant = rep(factor(101:200), 2),
    +           Timepoint = rep(c("First", "Second"), each = 100),
    +           Height = c(rnorm(100, 30, 5), rnorm(100, 50, 8)))
    +  )
    +
    +plants2 %>% 
    +  group_by(Species, Timepoint) %>% 
    +  summarize(across(Height, list(mean = mean, sd = sd), .names = "{col}_{fn}"))
    +
    +
    +
      # A tibble: 4 x 4
    +  # Groups:   Species [2]
    +    Species Timepoint Height_mean Height_sd
    +    <chr>   <chr>           <dbl>     <dbl>
    +  1 Dwarf   First            9.22      5.02
    +  2 Dwarf   Second          20.3       8.26
    +  3 Giant   First           30.8       4.80
    +  4 Giant   Second          49.9       8.40
    +
    +

    In this new plot, I just added facet_wrap(~Species)

    +
    +
    +
    plants2 %>% 
    +  arrange(Plant) %>% 
    +  ggplot(aes(Timepoint, Height, fill = Timepoint)) +
    +  geom_paired_raincloud() +
    +  geom_point(aes(group = Plant),
    +             position = position_nudge(c(.05, -.05)),
    +             alpha = 0.5, shape = 16,
    +             show.legend = FALSE) +
    +  geom_line(aes(group = Plant),
    +            position = position_nudge(c(.05, -.05))) +
    +  facet_wrap(~Species)
    +
    +
    +

    +
    +

    geom_paired_raincloud() isn’t particularly useful for plotting comparisons between more than two levels, so it throws a warning when that’s the case:

    +
    +
    +
    # Adding a third timepoint
    +plants3 <- plants %>% 
    +  bind_rows(tibble(Species = "Dwarf",
    +                   Plant = factor(1:100),
    +                   Timepoint = "Third",
    +                   Height = rnorm(100, 40, 10)))
    +
    +plants3 %>% 
    +  group_by(Timepoint) %>% 
    +  summarize(across(Height, list(mean = mean, sd = sd), .names = "{col}_{fn}"))
    +
    +
    +
      # A tibble: 3 x 3
    +    Timepoint Height_mean Height_sd
    +    <chr>           <dbl>     <dbl>
    +  1 First            9.22      5.02
    +  2 Second          20.3       8.26
    +  3 Third           39.8      11.2
    +
    +
    +
    +
    plants3 %>% 
    +  arrange(Plant) %>% 
    +  ggplot(aes(Timepoint, Height, fill = Timepoint)) +
    +  geom_paired_raincloud() +
    +  geom_point(aes(group = Plant),
    +             position = position_nudge(c(.05, -.05)),
    +             alpha = 0.5, shape = 16,
    +             show.legend = FALSE) +
    +  geom_line(aes(group = Plant),
    +            position = position_nudge(c(.05, -.05)))
    +
    +
    +

    +
    +

    But I think geom_paired_raincloud() works great if you have the right data. Here’s an example from my recent work, looking at the variation in how subjects respond to stimuli when they’re presented in one condition (Subject Accent) compared to the other (Verb Accent).

    +
    +

    +
    +

    The above plot is a combination of geom_paired_raincloud(), geom_point(), geom_line(), and geom_boxplot(). I like that you can employ all these aesthetics at once without making the plot too overwhelming. I’ve included the important part of the code here and the full code is available at the github repo for this research project.

    +
    +
    +
    rainplot_data %>% 
    +  ggplot(aes(x = Cond, y = z_RT, fill = Cond)) +
    +  geom_paired_raincloud(alpha = .5) +
    +  geom_point(aes(group = Item),
    +             position = position_nudge(c(.15, -.15)),
    +             alpha = .5, shape = 16) +
    +  geom_line(aes(group = Item),
    +            position = position_nudge(c(.13, -.13)),
    +            linetype = 3) +
    +  geom_boxplot(position = position_nudge(c(.07, -.07)),
    +               alpha = .5, width = .04, outlier.shape = " ") +
    +  facet_wrap(~Type, scales = "free_x") +
    +  ...
    +
    +
    +
    + +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-07-13-geom-paired-raincloud/preview.png b/docs/posts/2020-07-13-geom-paired-raincloud/preview.png new file mode 100644 index 00000000..f89c2d99 Binary files /dev/null and b/docs/posts/2020-07-13-geom-paired-raincloud/preview.png differ diff --git a/docs/posts/2020-07-20-shiny-tips-1/2020-07-20-shiny-tips-1_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-07-20-shiny-tips-1/2020-07-20-shiny-tips-1_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-07-20-shiny-tips-1/2020-07-20-shiny-tips-1_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-07-20-shiny-tips-1/index.html b/docs/posts/2020-07-20-shiny-tips-1/index.html new file mode 100644 index 00000000..898db82a --- /dev/null +++ b/docs/posts/2020-07-20-shiny-tips-1/index.html @@ -0,0 +1,2728 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Shiny tips - the first set + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Shiny tips - the first set

    + +
    + shiny +
    + +

    %||%, imap() + {shinybusy}, and user inputs in modalDialog()

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    07-20-2020 +
    + +
    +
    + +
    +

    When I was an RA in the LEARN lab - a child language development lab at Northwestern - I worked on a shiny app that automates snowball search for meta-analysis research (relevant research poster). Long story short, I worked on it for a couple months, got it working, then stopped working on it for another couple months, and had the chance to revisit it just recently.

    +

    When I picked the project back up, I realized that my old code was poorly commented, somewhat inefficient, and even hackish at times. So I decided to re-write it from scratch. In this second time around, I learned a lot of useful functions/tricks that really helped streamline my code and I thought I’d document my three favorite ones here for future reference.

    +

    1. %||% from {rlang}

    +

    Basically, %||% is an infix operator that returns the left-hand side when it is not Null and the right-hand side when it is Null. It’s from the {rlang} package but you can also define the function yourself:

    +
    +
    +
    "%||%" <- function(lhs, rhs) {
    +  if (is.null(lhs)) rhs else lhs
    +}
    +
    +a <- 10
    +b <- NULL
    +
    +a %||% b
    +
    +
    +
      [1] 10
    +
    +
    b %||% a
    +
    +
    +
      [1] 10
    +
    +
    # note how the output is different when b is no longer null
    +b <- 11
    +b %||% a
    +
    +
    +
      [1] 11
    +
    +

    I found this operator to be extremely useful when displaying empty tables as placeholders when using DT::datatable(). It allows me to communicate to the user where a table is expected to appear rather than just not showing anything at all when no data is loaded (which is what happens by default).

    +

    For example, if you want to show an empty column with an empty row when the data (here, the reactive variable mydf) is null, you might do the following:

    +
    +
    +
    mydf_display <- renderDataTable({
    +  datatable(mydf() %||% tibble(` ` = NA))
    +})
    +
    +
    +
    +

    Another use-case for %||% is when I’m trying a sequence of function calls until one one of them succeeds and returns a non-null value. For example, say I want to scrape some information online and I have API wrappers for different websites that potentially have that information. I can chain them together using %||% like so:

    +
    +
    +
    myinfo <- 
    +  scrape_website1() %||%
    +  scrape_website2() %||%
    +  scrape_website3()
    +
    +
    +
    +

    This is much neater than nested if…else statements!

    +

    2. purrr::imap() and {shinybusy}

    +

    Using my shiny app involves a lot of waiting (querying online databases), so I looked into ways to show a progress bar similar to the family of *Modal() functions from {shiny}. The extension package {shinybusy} (project site) offers a very satisfying solution to this problem.

    +

    Basically, you initialize a progress bar with show_modal_progress_*() and increment its value inside whatever operation you’re doing. Here’s a pseudo code demonstrating how it works:

    +
    +
    initialize a progress bar
    +
    +create a new_list of same size to store output
    +
    +for index in seq_along(list):
    +  new_list[index] <- calculations(list[index])
    +  increment progress bar by index
    +  
    +remove progress bar
    +
    +return new_list
    +
    +

    But in my case, my “do stuff” part didn’t involve a big wall of code because I packed it into a single function in a separate file that I source at the beginning. This, coupled with my general aversion to for-loops, drove me to imap() and its variants from {purrr}. imap() is like map() except it also keeps track of the index of the element that you’re operating on (to put it another way, it’s like map2() where .y is the index).

    +

    Now, you don’t need an explicit for-loop to increment and the above code can be reduced to this:

    +
    +
    initialize a progress bar
    +
    +new_list <- imap(list,
    +                 ~{
    +                   calculations(.x)
    +                   increment progress bar by .y
    +                 })
    +  
    +remove progress bar
    +
    +return new_list
    +
    +

    In my opinion, this is much cleaner! For a more concrete example, here’s a template using actual code:

    +
    +
    +
    my_data <- eventReactive(input$my_button, {
    +  
    +  # initialize a progress bar
    +  show_modal_progress_line()
    +  
    +  # do operation on elements of vector
    +  result <- imap(my_reactive_var(),
    +                 ~{
    +                   update_modal_progress(value = .y / length(my_reactive_var()))
    +                   my_operation_on_element(.x)
    +                 })
    +  
    +  # remove progress bar
    +  remove_modal_progress()
    +  
    +  # return output
    +  return(result)
    +  
    +})
    +
    +
    +
    +

    3. User inputs inside modalDialog()

    +

    In {shiny}, you can show the user a pop-up message box by first laying out the content of the message in modalDialog() and then rendering it with showModal(). In the first version of my app, I used this to show simple messages like warnings, but did you know that you can include any *Input widgets too?

    +

    For example, this code renders a pop-up box for a file upload in response to a button click:

    +
    +
    +
    observeEvent(input$MyButton, {
    +  showModal(modalDialogue(
    +    title = "Upload File Here",
    +    fileInput(inputID = "UploadedFile", label = "Upload")
    +  ))
    +})
    +
    +
    +
    +

    And you can access whatever is uploaded using input$UploadedFile like you would if the file upload widget was in the ui side of the app!

    +

    This took me a bit to get used to because you are defining the modal in the server side where the content of the modal looks like the ui side but can be accessed back at the server side. But this was life-changing and it opened up a lot of potential for my GUI to be less cluttered. Using this neat trick, I was able to move a large feature into a modal that would only be available upon a click of a button (it was a feature designed for a rare case scenario so I thought I’d save the user from having to see the entire interface for that if they don’t ask for it).

    +

    Ending note

    +

    The more I learn and use shiny, the less I feel like I know. I’m actually enjoying this stage of my progress because every new thing just absolutely wows me (and I hope to continue sharing what I learn - hence this being the “first set”). And very much looking forward to Hadley Wickham’s new book on shiny!

    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-07-20-shiny-tips-1/preview.png b/docs/posts/2020-07-20-shiny-tips-1/preview.png new file mode 100644 index 00000000..82d06586 Binary files /dev/null and b/docs/posts/2020-07-20-shiny-tips-1/preview.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/2020-07-29-six-years-of-my-spotify-playlists_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/2020-07-29-six-years-of-my-spotify-playlists_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/2020-07-29-six-years-of-my-spotify-playlists_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/index.html b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/index.html new file mode 100644 index 00000000..ae532e58 --- /dev/null +++ b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/index.html @@ -0,0 +1,3457 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Six years of my Spotify playlists + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Six years of my Spotify playlists

    + +
    + ggplot2 + gganimate + spotifyr + data wrangling + data visualization +
    + +

    An analysis of acoustic features with {spotifyr}

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    07-29-2020 +
    + +
    +
    + +
    +
    + +
    +

    Background

    +

    One of my longest running habits is making monthly playlists. At the start of every month, I create a new playlist for that month and add songs that I like. Some songs are carried over from the previous month’s playlist and others are songs that I newly discover, but they’re all representative of the songs that I’m “into” for that month.

    +

    I’ve been doing this for many years, and have the best record of my monthly playlists for the past 6 years, which is how long I’ve been using spotify. So when I saw people talking about {spotifyr} - an R wrapper for Spotify’s web API - on twitter, I decided to take a stab at analyzing my monthly playlists (code here).

    +

    +

    +

    +
    +

    Analysis #1 - Size of monthly playlists over time

    +

    When I first pulled information about my Spotify account, I noticed that I had some gaps in my monthly playlists. This was a special case of non-random missing data: when I didn’t make a new playlist for the month, it’s because I didn’t think that there was a substantial change in what I’m jamming to from the previous month. The {zoo} package, which I didn’t know about before, came in very handy here for dealing with this missingness with its na.locf() (Last Observation Carried Forward) function.

    +

    After some more cleaning steps, I first made a simple plot that counted the number of songs that each monthly playlist had.

    +

    +

    There are some interesting things I notice, and here’s some context for them.

    + +

    Analysis #2 - Audio features

    +

    The real deal of Spotify API is actually the audio features, which Spotify calculates using their special algorithms. Some of the features are listed in the table below (adopted from the documentation). Of these, I decided to narrow down to acousticness, danceability, energy, and valence because others didn’t really show much variation (e.g., I don’t listen to live-recorded music on Spotify, so liveness is always near zero).

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FeatureDescription
    acousticnessA confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.
    danceabilityDanceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.
    energyEnergy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.
    instrumentalnessPredicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.
    livenessDetects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.
    loudnessThe overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.
    speechinessSpeechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.
    tempoThe overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.
    valenceA measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).
    +
    +

    I was interested in looking at how my music taste changed over time, so for each monthly playlist, I calculated the mean values for these four features and made a line plot:

    +

    +

    Some things that pop out:

    + +

    +

    Analysis #3 - Songs during college

    +

    Next, I wanted to focus on my years in college, from Fall 2016 to Spring 2020. For this analysis, I defined time in terms of school years and quarters. While I was a college student, I often felt like the passage of time was defined in terms of quarters, so this scale felt appropriate.

    +

    Here is the same line plot, except the feature values are averaged by quarter instead of month, and the plot is now faceted by school year:

    +

    +

    Observations:

    + +

    Analysis #4 - “My Top 100” playlists

    +

    In my last analysis, I move from my monthly playlists to the end-of-the-year playlists that Spotify makes for you every year.

    +

    For this, I grabbed audio features of songs in my yearly top 100 playlists from 2016-2019. In this graph, each line represents a song and the top 10 most listened to song of each year are emphasized in black. The thick red line in each panel represents the average of the songs for that year.

    +

    +

    Some observations on the variation in audio features among my top 100 playlists:

    + +

    Conclusion

    +

    I didn’t really dig too deeply into the acoustic profile of the songs I listen to in this post, and I doubt that Spotify’s list of audio features are comprehensive enough to describe my music taste, but this was a cool exercise!

    +

    And although I ignored several of the audio features because they weren’t very informative for the songs I listen to, I thought I should at least leave a summary table showing the mean values for all features that I gave in the table above!

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FeatureDescriptionAverage
    acousticnessA confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.0.16
    danceabilityDanceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.0.64
    energyEnergy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.0.75
    instrumentalnessPredicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.0.02
    livenessDetects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.0.19
    loudnessThe overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.-4.95
    speechinessSpeechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.0.08
    tempoThe overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.120.25
    valenceA measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).0.55
    +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_animation.gif b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_animation.gif new file mode 100644 index 00000000..e61b4769 Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_animation.gif differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_plot.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_plot.png new file mode 100644 index 00000000..5d29c41d Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_ft_plot.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_plot.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_plot.png new file mode 100644 index 00000000..988ea3c2 Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/monthly_plot.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/preview.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/preview.png new file mode 100644 index 00000000..542bfd9a Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/preview.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/quarterly_ft_plot.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/quarterly_ft_plot.png new file mode 100644 index 00000000..bce2cb28 Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/quarterly_ft_plot.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/spotify.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/spotify.png new file mode 100644 index 00000000..695dbbc0 Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/spotify.png differ diff --git a/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/top_songs_plot.png b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/top_songs_plot.png new file mode 100644 index 00000000..4343d482 Binary files /dev/null and b/docs/posts/2020-07-29-six-years-of-my-spotify-playlists/top_songs_plot.png differ diff --git a/docs/posts/2020-08-04-tidytuesday-2020-week-32/index.html b/docs/posts/2020-08-04-tidytuesday-2020-week-32/index.html new file mode 100644 index 00000000..2287da80 --- /dev/null +++ b/docs/posts/2020-08-04-tidytuesday-2020-week-32/index.html @@ -0,0 +1,2732 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 Week 32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 Week 32

    + +
    + tidytuesday + data visualization + ggplot2 +
    + +

    A dumbbell chart visualization of energy production trends among European countries

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    08-04-2020 +
    + +
    +
    + +
    +
    + +
    +

    Visualization

    +

     

    +
    +

    +
    +

    Things I learned

    + +

    Things to improve

    + +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +library(tidytuesdayR)
    +library(lemon)
    +library(ggalt)
    +library(patchwork)
    +library(extrafont)
    +
    +theme_set(theme_classic())
    +
    +### Data
    +
    +tuesdata <- tidytuesdayR::tt_load('2020-08-04')
    +
    +energy_types <- tuesdata$energy_types
    +
    +energy_types_tidy <- energy_types %>% 
    +  pivot_longer(where(is.double), names_to = "Year", values_to = "GWh")
    +
    +
    +plot_data <- energy_types_tidy %>% 
    +  add_count(country, Year, wt = GWh, name = "Total") %>% 
    +  mutate(GWh_prop = GWh/Total) %>% 
    +  select(-country_name, -GWh, -Total , -level) %>% 
    +  filter(Year %in% c(2016, 2018))
    +  
    +
    +### Plotting
    +
    +p1 <- plot_data %>% 
    +  filter(type == "Conventional thermal") %>% 
    +  pivot_wider(names_from = Year, values_from = GWh_prop) %>% 
    +  mutate(country = fct_reorder(country, `2018`, max, .desc = TRUE)) %>% 
    +  mutate(increase = (`2018` - `2016`) > 0) %>%  
    +  ggplot() +
    +  geom_dumbbell(
    +    aes(y = country, x = `2016`, xend = `2018`, color = increase),
    +    dot_guide = TRUE, dot_guide_size = 0.25,
    +    size = 2, colour_x = "#babfb6", colour_xend = "#5f787b"
    +  ) +
    +  scale_color_manual(values = c("#d69896", "#a1cf86"), labels = c("2016", "2018")) +
    +  guides(color = guide_legend(override.aes = list(color = c("#babfb6", "#5f787b"), size = 3))) +
    +  labs(title = "Conventional Thermal Energy",
    +       y = "Country Codes",
    +       color = NULL) +
    +  theme(legend.position = c(.75, .85),
    +        axis.title.y = element_text(size = 12, vjust = 5))
    +
    +p2 <- plot_data %>% 
    +  filter(type != "Conventional thermal") %>% 
    +  pivot_wider(names_from = Year, values_from = GWh_prop) %>% 
    +  mutate(type = fct_lump(type, n = 3, w = `2018`)) %>% 
    +  group_by(type, country) %>% 
    +  summarize(`2016` = sum(`2016`), `2018` = sum(`2018`)) %>% 
    +  slice_max(`2018`, n = 10, with_ties = FALSE) %>% 
    +  mutate(country = tidytext::reorder_within(country, `2018`, type)) %>% 
    +  mutate(increase = (`2018` - `2016`) > 0) %>%  
    +  ggplot() +
    +  geom_dumbbell(
    +    aes(y = country, x = `2016`, xend = `2018`, color = increase),
    +    dot_guide = TRUE, dot_guide_size = .4,
    +    size = 2.5, colour_x = "#babfb6", colour_xend = "#5f787b",
    +    show.legend = FALSE
    +  ) +
    +  scale_color_manual(values = c("#d69896", "#a1cf86")) +
    +  tidytext::scale_y_reordered() +
    +  facet_rep_wrap(~type, scales = "free_y") +
    +  labs(title = "Clean Energy",
    +       subtitle = "Leaders in Each Category (Top 10)",
    +       y = NULL)
    +
    +patched <- p1 + p2 &
    +    coord_capped_cart(bottom = "both") &
    +    scale_x_continuous(labels = scales::percent) &
    +    labs(x = NULL) &
    +    theme(
    +      plot.title = element_text(hjust = 0.5, size = 16, face = "bold"),
    +      text = element_text(family = "Montserrat"),
    +      panel.grid.major.y = element_blank(),
    +      plot.margin = unit(c(.4,.2,.2,.4), "cm"),
    +      plot.background = element_rect(color = "transparent")
    +    )
    +
    +patched + plot_annotation(title = "Electricity Production in Europe",
    +                  subtitle = "A comparison between 2016 and 2018",
    +                  caption = "Percent Accounting for the Country's Total Electricity Generated",
    +                  theme = list(plot.title = element_text(size = 22),
    +                               plot.subtitle = element_text(face = "italic", hjust = .5),
    +                               plot.caption = element_text(size = 12, hjust = .5)))
    +
    +
    +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-08-04-tidytuesday-2020-week-32/preview.png b/docs/posts/2020-08-04-tidytuesday-2020-week-32/preview.png new file mode 100644 index 00000000..8f0b26b0 Binary files /dev/null and b/docs/posts/2020-08-04-tidytuesday-2020-week-32/preview.png differ diff --git a/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/figure-html5/plot-1.png b/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/figure-html5/plot-1.png new file mode 100644 index 00000000..8f976635 Binary files /dev/null and b/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/figure-html5/plot-1.png differ diff --git a/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-08-04-tidytuesday-2020-week-32/tidytuesday-2020-week-32_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-08-07-saving-a-line-of-piping/index.html b/docs/posts/2020-08-07-saving-a-line-of-piping/index.html new file mode 100644 index 00000000..d23546f8 --- /dev/null +++ b/docs/posts/2020-08-07-saving-a-line-of-piping/index.html @@ -0,0 +1,3105 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Saving a line of piping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Saving a line of piping

    + +
    + data wrangling + dplyr + tutorial +
    + +

    Some notes on lesser known functions/functionalities that combine common chain of {dplyr} verbs.

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    08-07-2020 +
    + +
    +
    + +
    +
    + +
    +
    + +
    +

    Using a cleaned up version of penguins data from {palmerpenguins}:

    +
    +
    +
    data("penguins", package = "palmerpenguins")
    +
    +penguins <- na.omit(penguins)
    +
    +
    +
    +
    +
    + +
    +

    1. rename() inside select()

    +

    You can rename a column inside select() by assigning a new name on the left hand side:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   select(species, island) %>% 
    +#   rename(penguin_species = species)
    +
    +penguins %>% 
    +  select(penguin_species = species,
    +         island)
    +
    +
    +
      # A tibble: 333 x 2
    +     penguin_species island   
    +     <fct>           <fct>    
    +   1 Adelie          Torgersen
    +   2 Adelie          Torgersen
    +   3 Adelie          Torgersen
    +   4 Adelie          Torgersen
    +   5 Adelie          Torgersen
    +   6 Adelie          Torgersen
    +   7 Adelie          Torgersen
    +   8 Adelie          Torgersen
    +   9 Adelie          Torgersen
    +  10 Adelie          Torgersen
    +  # ... with 323 more rows
    +
    +

    This also works with {tidyselect} helpers like starts_with(), ends_with(), contains(), and matches():

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   select(species, island) %>% 
    +#   rename(penguin_species = species,
    +#          weight = body_weight_g)
    +
    +penguins %>% 
    +  select(penguin_species = species,
    +         island,
    +         weight = contains("mass"))
    +
    +
    +
      # A tibble: 333 x 3
    +     penguin_species island    weight
    +     <fct>           <fct>      <int>
    +   1 Adelie          Torgersen   3750
    +   2 Adelie          Torgersen   3800
    +   3 Adelie          Torgersen   3250
    +   4 Adelie          Torgersen   3450
    +   5 Adelie          Torgersen   3650
    +   6 Adelie          Torgersen   3625
    +   7 Adelie          Torgersen   4675
    +   8 Adelie          Torgersen   3200
    +   9 Adelie          Torgersen   3800
    +  10 Adelie          Torgersen   4400
    +  # ... with 323 more rows
    +
    +

    2. rename() inside count()

    +

    You can rename the new column of counts (n by default) using the name argument:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   count(species) %>% 
    +#   rename(total = n)
    +
    +penguins %>% 
    +  count(species, name = "total")
    +
    +
    +
      # A tibble: 3 x 2
    +    species   total
    +    <fct>     <int>
    +  1 Adelie      146
    +  2 Chinstrap    68
    +  3 Gentoo      119
    +
    +

    You can also rename the column(s) that are selected for counting in the same way as shown in the select() examples above:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   count(species) %>% 
    +#   rename(total = n,
    +#          penguin_species = species)
    +
    +penguins %>% 
    +  count(penguin_species = species, name = "total")
    +
    +
    +
      # A tibble: 3 x 2
    +    penguin_species total
    +    <fct>           <int>
    +  1 Adelie            146
    +  2 Chinstrap          68
    +  3 Gentoo            119
    +
    +

    Note that the new name passed into the name argument must be quoted, but the new name for selected column needs not to be unquoted:

    +
    +
    +
    identical(
    +  # Method 1: new column name UNQUOTED
    +  penguins %>% 
    +    count(penguin_species = species, name = "total"),
    +  # Method 2: new column name QUOTED
    +  penguins %>% 
    +    count("penguin_species" = species, name = "total") 
    +)
    +
    +
    +
      [1] TRUE
    +
    +

    I prefer to unquote the new column names to keep it consistent with the recommended style for rename()

    +

    This feature of select() may seem weird and hackish (and I guess it sort of is in this demonstration) but it’s explicitly documented here if you want to read more on it.

    +

    3. mutate() inside count()

    +

    You can also create a new column to count by inside count(). This works very similarly to the above, but I think it’s worth its own mention.

    +

    It’s pretty simple - you just do what you’d do for mutate() inside count():

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   mutate(long_beak = bill_length_mm > 50) %>% 
    +#   count(long_beak)
    +
    +penguins %>% 
    +  count(long_beak = bill_length_mm > 50)
    +
    +
    +
      # A tibble: 2 x 2
    +    long_beak     n
    +    <lgl>     <int>
    +  1 FALSE       281
    +  2 TRUE         52
    +
    +

    And of course, this also works when specifying multiple variables to count by:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   mutate(long_beak = bill_length_mm > 50,
    +#          is_adelie = species == "Adelie") %>% 
    +#   count(is_adelie, long_beak)
    +
    +penguins %>% 
    +  count(long_beak = bill_length_mm > 50,
    +        is_adelie = species == "Adelie")
    +
    +
    +
      # A tibble: 3 x 3
    +    long_beak is_adelie     n
    +    <lgl>     <lgl>     <int>
    +  1 FALSE     FALSE       135
    +  2 FALSE     TRUE        146
    +  3 TRUE      FALSE        52
    +
    +

    4. transmute() + select()

    +

    transmute() is a function that mutates columns and returns only those columns:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   mutate(body_mass_kg = body_mass_g/1000) %>% 
    +#   select(body_mass_kg)
    +
    +penguins %>% 
    +  transmute(body_mass_kg = body_mass_g/1000)
    +
    +
    +
      # A tibble: 333 x 1
    +     body_mass_kg
    +            <dbl>
    +   1         3.75
    +   2         3.8 
    +   3         3.25
    +   4         3.45
    +   5         3.65
    +   6         3.62
    +   7         4.68
    +   8         3.2 
    +   9         3.8 
    +  10         4.4 
    +  # ... with 323 more rows
    +
    +

    I’ve rarely used transmute() in the past because I thought it could only return modified columns, which would be very limiting (like in the above example, what good is a single column of penguin body mass in kilograms?)

    +

    But actually you can just name the columns you want to include in transmute() like you would in select() to carry over columns that you aren’t modifying. And of course, you can “rename” them as you do it1:

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   mutate(body_mass_kg = body_mass_g/1000) %>% 
    +#   select(species, island, body_mass_kg) %>% 
    +#   rename(penguin_species = species)
    +
    +penguins %>% 
    +  transmute(penguin_species = species,
    +            island,
    +            body_mass_kg = body_mass_g/1000)
    +
    +
    +
      # A tibble: 333 x 3
    +     penguin_species island    body_mass_kg
    +     <fct>           <fct>            <dbl>
    +   1 Adelie          Torgersen         3.75
    +   2 Adelie          Torgersen         3.8 
    +   3 Adelie          Torgersen         3.25
    +   4 Adelie          Torgersen         3.45
    +   5 Adelie          Torgersen         3.65
    +   6 Adelie          Torgersen         3.62
    +   7 Adelie          Torgersen         4.68
    +   8 Adelie          Torgersen         3.2 
    +   9 Adelie          Torgersen         3.8 
    +  10 Adelie          Torgersen         4.4 
    +  # ... with 323 more rows
    +
    +

    5. ungroup() inside summarize()

    +

    I always found using ungroup() after summarize() to be extremely ugly, but I found myself using it a lot to remove left-over groupings after a summarize call:

    +
    +
    +
    penguins %>% 
    +  group_by(island, species) %>% 
    +  summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% 
    +  ungroup()
    +
    +
    +
      # A tibble: 5 x 3
    +    island    species   mean_mass
    +    <fct>     <fct>         <dbl>
    +  1 Biscoe    Adelie        3710.
    +  2 Biscoe    Gentoo        5092.
    +  3 Dream     Adelie        3701.
    +  4 Dream     Chinstrap     3733.
    +  5 Torgersen Adelie        3709.
    +
    +

    … because summarize() only drops the last grouping variable by defaut, meaning that the output is still grouped by the island variable if ungroup() isn’t called:

    +
    +
    +
    # Without ungroup()
    +penguins %>% 
    +  group_by(island, species) %>% 
    +  summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% 
    +  group_vars()
    +
    +
    +
      [1] "island"
    +
    +
    # With ungroup()
    +penguins %>% 
    +  group_by(island, species) %>% 
    +  summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% 
    +  ungroup() %>% 
    +  group_vars()
    +
    +
    +
      character(0)
    +
    +

    Since {dplyr} 1.0.0, you can simply set the .groups argument inside summarize() to 'drop' to achieve the same:

    +
    +
    +
    penguins %>% 
    +  group_by(island, species) %>% 
    +  summarize(mean_mass = mean(body_mass_g, na.rm = TRUE), .groups = 'drop')
    +
    +
    +
      # A tibble: 5 x 3
    +    island    species   mean_mass
    +    <fct>     <fct>         <dbl>
    +  1 Biscoe    Adelie        3710.
    +  2 Biscoe    Gentoo        5092.
    +  3 Dream     Adelie        3701.
    +  4 Dream     Chinstrap     3733.
    +  5 Torgersen Adelie        3709.
    +
    +

    But ungroup() still remains relevant as you can now selectively remove grouping variables in {dplyr} 1.0.0.

    +

    6. arrange() + other features inside slice()

    +

    In past versions of {dplyr}, if you wanted to grab the top n rows sorted by a column, you’d use top_n(), which provides a simpler way of doing slice() + arrange():

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   arrange(desc(body_mass_g)) %>% 
    +#   slice(1:5)
    +
    +penguins %>% 
    +  top_n(5, wt = body_mass_g)
    +
    +
    +
      # A tibble: 6 x 8
    +    species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex  
    +    <fct>   <fct>           <dbl>         <dbl>            <int>       <int> <fct>
    +  1 Gentoo  Biscoe           49.2          15.2              221        6300 male 
    +  2 Gentoo  Biscoe           59.6          17                230        6050 male 
    +  3 Gentoo  Biscoe           51.1          16.3              220        6000 male 
    +  4 Gentoo  Biscoe           45.2          16.4              223        5950 male 
    +  5 Gentoo  Biscoe           49.8          15.9              229        5950 male 
    +  6 Gentoo  Biscoe           48.8          16.2              222        6000 male 
    +  # ... with 1 more variable: year <int>
    +
    +

    But the recent {dplyr} 1.0.0 augmented slice() with variants like slice_min() and slice_max() that now supresede top_n():

    +
    +
    +
    ##### Pre-1.0.0 #####
    +# penguins %>% 
    +#   top_n(5, wt = body_mass_g)
    +
    +penguins %>% 
    +  slice_max(order_by = body_mass_g, n = 5)
    +
    +
    +
      # A tibble: 6 x 8
    +    species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex  
    +    <fct>   <fct>           <dbl>         <dbl>            <int>       <int> <fct>
    +  1 Gentoo  Biscoe           49.2          15.2              221        6300 male 
    +  2 Gentoo  Biscoe           59.6          17                230        6050 male 
    +  3 Gentoo  Biscoe           51.1          16.3              220        6000 male 
    +  4 Gentoo  Biscoe           48.8          16.2              222        6000 male 
    +  5 Gentoo  Biscoe           45.2          16.4              223        5950 male 
    +  6 Gentoo  Biscoe           49.8          15.9              229        5950 male 
    +  # ... with 1 more variable: year <int>
    +
    +

    Note that the order of arguments is different for slice_min/max() - the first argument after piping is where you specify the variable for ordering rather than the number of rows to return, like in top_n().

    +

    This is because slice_min/max() gives you an option to either specify a certain number of rows n or a proportion of rows prop:

    +
    +
    +
    penguins %>% 
    +  slice_max(body_mass_g, prop = .01)
    +
    +
    +
      # A tibble: 4 x 8
    +    species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex  
    +    <fct>   <fct>           <dbl>         <dbl>            <int>       <int> <fct>
    +  1 Gentoo  Biscoe           49.2          15.2              221        6300 male 
    +  2 Gentoo  Biscoe           59.6          17                230        6050 male 
    +  3 Gentoo  Biscoe           51.1          16.3              220        6000 male 
    +  4 Gentoo  Biscoe           48.8          16.2              222        6000 male 
    +  # ... with 1 more variable: year <int>
    +
    +

    And actually, the most significant change with the new slice_*() functions is from adding appropriate behavior for grouped dataframes.

    +

    So for example, this example below returns the top 5% of penguins by weight for each species:

    +
    +
    +
    penguins %>% 
    +  group_by(species) %>% 
    +  slice_max(body_mass_g, prop = .05)
    +
    +
    +
      # A tibble: 16 x 8
    +  # Groups:   species [3]
    +     species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g
    +     <fct>   <fct>           <dbl>         <dbl>            <int>       <int>
    +   1 Adelie  Biscoe           43.2          19                197        4775
    +   2 Adelie  Biscoe           41            20                203        4725
    +   3 Adelie  Torge~           42.9          17.6              196        4700
    +   4 Adelie  Torge~           39.2          19.6              195        4675
    +   5 Adelie  Dream            39.8          19.1              184        4650
    +   6 Adelie  Dream            39.6          18.8              190        4600
    +   7 Adelie  Biscoe           45.6          20.3              191        4600
    +   8 Chinst~ Dream            52            20.7              210        4800
    +   9 Chinst~ Dream            52.8          20                205        4550
    +  10 Chinst~ Dream            53.5          19.9              205        4500
    +  11 Gentoo  Biscoe           49.2          15.2              221        6300
    +  12 Gentoo  Biscoe           59.6          17                230        6050
    +  13 Gentoo  Biscoe           51.1          16.3              220        6000
    +  14 Gentoo  Biscoe           48.8          16.2              222        6000
    +  15 Gentoo  Biscoe           45.2          16.4              223        5950
    +  16 Gentoo  Biscoe           49.8          15.9              229        5950
    +  # ... with 2 more variables: sex <fct>, year <int>
    +
    +

    But note that slice_*() functions do not modify groups in the result if the input is a grouped dataframe, so you need to explicitly add a call to ungroup() if you want to drop groups after slicing.

    +

    7. count and sum by group with add_count()

    +

    Saving my favorite lesser-known {dplyr} function for last!

    +

    add_count() adds a column with the counts of each group (or combination of groups):

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   group_by(species) %>% 
    +#   mutate(count_by_species = n()) %>% 
    +#   ungroup()
    +
    +penguins %>% 
    +  add_count(species, name = "count_by_species") %>% 
    +  # cutting down some columns to show the new column
    +  select(-contains("mm"))
    +
    +
    +
      # A tibble: 333 x 6
    +     species island    body_mass_g sex     year count_by_species
    +     <fct>   <fct>           <int> <fct>  <int>            <int>
    +   1 Adelie  Torgersen        3750 male    2007              146
    +   2 Adelie  Torgersen        3800 female  2007              146
    +   3 Adelie  Torgersen        3250 female  2007              146
    +   4 Adelie  Torgersen        3450 female  2007              146
    +   5 Adelie  Torgersen        3650 male    2007              146
    +   6 Adelie  Torgersen        3625 female  2007              146
    +   7 Adelie  Torgersen        4675 male    2007              146
    +   8 Adelie  Torgersen        3200 female  2007              146
    +   9 Adelie  Torgersen        3800 male    2007              146
    +  10 Adelie  Torgersen        4400 male    2007              146
    +  # ... with 323 more rows
    +
    +

    You can use the wt to effectively get sums by group (perhaps hackish but very very useful):

    +
    +
    +
    ##### Long Form #####
    +# penguins %>% 
    +#   group_by(species) %>% 
    +#   mutate(total_weight_by_species = sum(body_mass_g)) %>% 
    +#   ungroup()
    +  
    +
    +penguins %>% 
    +  add_count(species, wt = body_mass_g, name = "total_weight_by_species") %>% 
    +    # cutting down some columns to show the new column
    +  select(-contains("mm"))
    +
    +
    +
      # A tibble: 333 x 6
    +     species island    body_mass_g sex     year total_weight_by_species
    +     <fct>   <fct>           <int> <fct>  <int>                   <int>
    +   1 Adelie  Torgersen        3750 male    2007                  541100
    +   2 Adelie  Torgersen        3800 female  2007                  541100
    +   3 Adelie  Torgersen        3250 female  2007                  541100
    +   4 Adelie  Torgersen        3450 female  2007                  541100
    +   5 Adelie  Torgersen        3650 male    2007                  541100
    +   6 Adelie  Torgersen        3625 female  2007                  541100
    +   7 Adelie  Torgersen        4675 male    2007                  541100
    +   8 Adelie  Torgersen        3200 female  2007                  541100
    +   9 Adelie  Torgersen        3800 male    2007                  541100
    +  10 Adelie  Torgersen        4400 male    2007                  541100
    +  # ... with 323 more rows
    +
    +

    Also check out its more primitive version add_tally().

    +

    By default, add_tally() adds a count of rows, which you can already do with mutate(n = n()), but it shines when you make use of its wt argument:

    +
    +
    +
    penguins %>% 
    +  add_count(species, wt = body_mass_g, name = "total_weight_by_species") %>% 
    +  add_tally(wt = body_mass_g, name = "total_weight_of_all_species") %>% 
    +  select(1:2, last_col(0):last_col(1))
    +
    +
    +
      # A tibble: 333 x 4
    +     species island    total_weight_of_all_species total_weight_by_species
    +     <fct>   <fct>                           <int>                   <int>
    +   1 Adelie  Torgersen                     1400950                  541100
    +   2 Adelie  Torgersen                     1400950                  541100
    +   3 Adelie  Torgersen                     1400950                  541100
    +   4 Adelie  Torgersen                     1400950                  541100
    +   5 Adelie  Torgersen                     1400950                  541100
    +   6 Adelie  Torgersen                     1400950                  541100
    +   7 Adelie  Torgersen                     1400950                  541100
    +   8 Adelie  Torgersen                     1400950                  541100
    +   9 Adelie  Torgersen                     1400950                  541100
    +  10 Adelie  Torgersen                     1400950                  541100
    +  # ... with 323 more rows
    +
    +
    +
    +
    +
      +
    1. What happens under the hood is actually copying of a sort, so this is probably not the best approach if you care about efficiency. As a case in point, you can’t use {tidyselect} helpers in transmute because you’re creating a new dataframe↩︎

    2. +
    +
    + +
    + +
    + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-08-07-saving-a-line-of-piping/preview.png b/docs/posts/2020-08-07-saving-a-line-of-piping/preview.png new file mode 100644 index 00000000..3eeca633 Binary files /dev/null and b/docs/posts/2020-08-07-saving-a-line-of-piping/preview.png differ diff --git a/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/htmlwidgets-1.5.1/htmlwidgets.js b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/htmlwidgets-1.5.1/htmlwidgets.js new file mode 100644 index 00000000..6f3d672d --- /dev/null +++ b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/htmlwidgets-1.5.1/htmlwidgets.js @@ -0,0 +1,903 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval(code); + } catch(error) { + if (!error instanceof SyntaxError) { + throw error; + } + try { + result = eval("(" + code + ")"); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + if (cel) { + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + } + + return { + getWidth: function() { return cel.offsetWidth; }, + getHeight: function() { return cel.offsetHeight; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return el.offsetWidth; }, + getHeight: function() { return el.offsetHeight; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
    ").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var result = bindingDef.initialize(el, el.offsetWidth, + el.offsetHeight); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + initResult = binding.initialize(el, + sizeObj ? sizeObj.getWidth() : el.offsetWidth, + sizeObj ? sizeObj.getHeight() : el.offsetHeight + ); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + var resizeHandler = function(e) { + var size = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); + diff --git a/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/reactable-binding-0.2.0/reactable.js b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/reactable-binding-0.2.0/reactable.js new file mode 100644 index 00000000..308f474f --- /dev/null +++ b/docs/posts/2020-08-07-saving-a-line-of-piping/saving-a-line-of-piping_files/reactable-binding-0.2.0/reactable.js @@ -0,0 +1,7 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,r),a.l=!0,a.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)r.d(n,a,function(t){return e[t]}.bind(null,a));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=20)}([function(e,t,r){e.exports=r(13)()},function(e,t){e.exports=window.React},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReactTableDefaults=void 0;var n=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,a=!1,o=void 0;try{for(var i,l=e[Symbol.iterator]();!(n=(i=l.next()).done)&&(r.push(i.value),!t||r.length!==t);n=!0);}catch(e){a=!0,o=e}finally{try{!n&&l.return&&l.return()}finally{if(a)throw o}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},a=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:[],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;return[t.map((function(t,i){o++;var l=a({},t,{_viewIndex:o}),s=r.concat([i]);if(l[U]&&u.default.get(re,s)){var c=e(l[U],s,o),f=n(c,2);l[U]=f[0],o=f[1]}return l})),o]}(Ae),Ie=n(Me,1);Ae=Ie[0];var Le=Z>0,We=Z+12&&void 0!==arguments[2]?arguments[2]:[],i={original:r[J],row:r,index:r[$],viewIndex:++Be,pageSize:Y,page:Z,level:o.length,nestingPath:o.concat([n]),aggregated:r[V],groupedByPivot:r[q],subRows:r[U]},c=u.default.get(re,i.nestingPath),f=P(He,i,void 0,e),d=u.default.splitProps(C(He,i,void 0,e));return l.default.createElement(se,a({key:i.nestingPath.join("_")},f),l.default.createElement(ue,a({className:d.className,style:d.style},d.rest),Oe.map((function(t,n){var o=te.find((function(e){return e.id===t.id}))||{},f="function"==typeof t.show?t.show():t.show,d=u.default.getFirstDefined(o.value,t.width,t.minWidth),p=u.default.getFirstDefined(o.value,t.width,t.maxWidth),g=u.default.splitProps(O(He,i,t,e)),h=u.default.splitProps(t.getProps(He,i,t,e)),m=[g.className,t.className,h.className],b=a({},g.style,t.style,h.style),y=a({},i,{isExpanded:c,column:a({},t),value:i.row[t.id],pivoted:t.pivoted,expander:t.expander,resized:te,show:f,width:d,maxWidth:p,tdProps:g,columnProps:h,classes:m,styles:b}),v=y.value,w=void 0,x=void 0,S=void 0,P=u.default.normalizeComponent(t.Cell,y,v),C=t.Aggregated||(t.aggregate?t.Cell:xe),k=t.Expander||ye,T=t.PivotValue||ve,j=we||function(e){return l.default.createElement("div",null,l.default.createElement(k,e),l.default.createElement(T,e))},E=t.Pivot||j;(y.pivoted||y.expander)&&(y.expandable=!0,w=!0,y.pivoted&&!y.subRows&&(y.expandable=!1,w=!1)),y.pivoted?(x=i.row[B]===t.id&&y.subRows,S=G.indexOf(t.id)>G.indexOf(i.row[B])&&y.subRows,P=x?u.default.normalizeComponent(E,a({},y,{value:r[H]}),r[H]):S?u.default.normalizeComponent(C,y,v):null):y.aggregated&&(P=u.default.normalizeComponent(C,y,v)),y.expander&&(P=u.default.normalizeComponent(k,y,r[H]),G&&(y.groupedByPivot&&(P=null),y.subRows||he||(P=null)));var R=w?function(t){var r=u.default.clone(re);return r=c?u.default.set(r,y.nestingPath,!1):u.default.set(r,y.nestingPath,{}),e.setStateWithData({expanded:r},(function(){ae&&ae(r,y.nestingPath,t)}))}:void 0,N={onClick:R};return g.rest.onClick&&(N.onClick=function(e){g.rest.onClick(e,R?function(){return R(e)}:void 0)}),h.rest.onClick&&(N.onClick=function(e){h.rest.onClick(e,R?function(){return R(e)}:void 0)}),l.default.createElement(fe,a({key:n+"-"+t.id,className:(0,s.default)(m,!f&&"hidden",y.expandable&&"rt-expandable",(x||S)&&"rt-pivot"),style:a({},b,{flex:d+" 0 auto",width:u.default.asPx(d),maxWidth:u.default.asPx(p)})},g.rest,h.rest,N),P)}))),i.subRows&&c&&i.subRows.map((function(e,r){return t(e,r,i.nestingPath)})),he&&!i.subRows&&c&&he(i))}(t,r)})),ze.map(Je)),_e?(n=k(He,void 0,void 0,e),c=u.default.splitProps(T(He,void 0,void 0,e)),l.default.createElement(de,a({className:n.className,style:a({},n.style,{minWidth:Ke+"px"})},n.rest),l.default.createElement(ue,a({className:(0,s.default)(c.className),style:c.style},c.rest),Oe.map(qe)))):null),D&&_?l.default.createElement("div",{className:"pagination-bottom"},j):null,!Ae.length&&l.default.createElement(me,et,u.default.normalizeComponent(I)),l.default.createElement(ge,a({loading:X,loadingText:M},Qe)))};return r?r(He,rt,this):rt()}}]),t}((0,f.default)((0,c.default)(i.Component)));h.propTypes=p.default,h.defaultProps=d.default,t.default=h},function(e,t){e.exports=window.reactR},function(e,t,r){var n; +/*! + Copyright (c) 2017 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}function s(e){return Array.isArray(e)}function u(e){return function e(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(s(t))for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1],r=arguments[2],n=u(t),a=void 0,o=e;for(;(a=n.shift())&&n.length;)o[a]||(o[a]={}),o=o[a];return o[a]=r,e},takeRight:function(e,t){var r=t>e.length?0:e.length-t;return e.slice(r)},last:function(e){return e[e.length-1]},orderBy:function(e,t,r,n){return e.sort((function(e,a){for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e;return"function"==typeof e?Object.getPrototypeOf(e).isReactComponent?a.default.createElement(e,t):e(t):r},asPx:function(e){return e=Number(e),Number.isNaN(e)?null:e+"px"}}},function(e,t,r){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=function(e,t){var r=e[1]||"",n=e[3];if(!n)return r;if(t&&"function"==typeof btoa){var a=(i=n,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */"),o=n.sources.map((function(e){return"/*# sourceURL="+n.sourceRoot+e+" */"}));return[r].concat(o).concat([a]).join("\n")}var i;return[r].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+r+"}":r})).join("")},t.i=function(e,r){"string"==typeof e&&(e=[[null,e,""]]);for(var n={},a=0;a=0&&f.splice(t,1)}function b(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var n=function(){0;return r.nc}();n&&(e.attrs.nonce=n)}return y(t,e.attrs),h(e,t),t}function y(e,t){Object.keys(t).forEach((function(r){e.setAttribute(r,t[r])}))}function v(e,t){var r,n,a,o;if(t.transform&&e.css){if(!(o="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=o}if(t.singleton){var i=c++;r=u||(u=b(t)),n=S.bind(null,r,i,!1),a=S.bind(null,r,i,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(r=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),h(e,t),t}(t),n=C.bind(null,r,t),a=function(){m(r),r.href&&URL.revokeObjectURL(r.href)}):(r=b(t),n=P.bind(null,r),a=function(){m(r)});return n(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;n(e=t)}else a()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=i()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var r=g(e,t);return p(r,t),function(e){for(var n=[],a=0;a=a.pages?a.pages-1:a.page,0)),this.setState(a,(function(){t&&t(),n.page===a.page&&n.pageSize===a.pageSize&&n.sorted===a.sorted&&n.filtered===a.filtered||r.fireFetchData()}))}}]),t}(e)}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,a=!1,o=void 0;try{for(var i,l=e[Symbol.iterator]();!(n=(i=l.next()).done)&&(r.push(i.value),!t||r.length!==t);n=!0);}catch(e){a=!0,o=e}finally{try{!n&&l.return&&l.return()}finally{if(a)throw o}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=Object.assign||function(e){for(var t=1;t-1)&&s.default.getFirstDefined(e.show,!0)}));return o({},e,{columns:r})}return e}))).filter((function(e){return e.columns?e.columns.length:!(u.indexOf(e.id)>-1)&&s.default.getFirstDefined(e.show,!0)}))).findIndex((function(e){return e.pivot}));u.length&&function(){var e=[];u.forEach((function(t){var r=k.find((function(e){return e.id===t}));r&&e.push(r)}));var r=e.reduce((function(e,t){return e&&e===t.parentColumn&&t.parentColumn}),e[0].parentColumn),n=S&&r.Header,a={Header:n=n||function(){return l.default.createElement("strong",null,"Pivoted")},columns:e.map((function(e){return o({},t.props.pivotDefaults,e,{pivoted:!0})}))};E>=0?(a=o({},T[E],a),T.splice(E,1,a)):T.unshift(a)}();var R=[],N=[],A=function(e,r){R.push(o({},t.props.column,r,{columns:e})),N=[]};T.forEach((function(e,t){if(e.columns)return j=j.concat(e.columns),N.length>0&&A(N),void A(e.columns,e);j.push(e),N.push(e)})),S&&N.length>0&&A(N);var D=d.map((function(e,t){return function e(t,r){var n,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=(c(n={},y,t),c(n,v,r),c(n,h,t[h]),c(n,b,a),n);return k.forEach((function(e){e.expander||(o[e.id]=e.accessor(t))})),o[h]&&(o[h]=o[h].map((function(t,r){return e(t,r,a+1)}))),o}(e,t)})),z=function(e){var t={};return _.forEach((function(r){var n=e.map((function(e){return e[r.id]}));t[r.id]=r.aggregate(n,e)})),t},_=j.filter((function(e){return!e.expander&&e.aggregate}));return u.length&&(D=function e(t,r){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(a===r.length)return t;var i=Object.entries(s.default.groupBy(t,r[a])).map((function(e){var t,o=n(e,2),i=o[0],l=o[1];return c(t={},p,r[a]),c(t,g,i),c(t,r[a],i),c(t,h,l),c(t,b,a),c(t,w,!0),t}));return i=i.map((function(t){var n,i=e(t[h],r,a+1);return o({},t,(c(n={},h,i),c(n,m,!0),n),z(i))}))}(D,u)),o({},e,{resolvedData:D,allVisibleColumns:j,headerGroups:R,allDecoratedColumns:k,hasHeaderGroups:S})}},{key:"getSortedData",value:function(e){var t=e.manual,r=e.sorted,n=e.filtered,a=e.defaultFilterMethod,o=e.resolvedData,i=e.allVisibleColumns,l=e.allDecoratedColumns,s={};return l.filter((function(e){return e.sortMethod})).forEach((function(e){s[e.id]=e.sortMethod})),{sortedData:t?o:this.sortData(this.filterData(o,n,a,i),r,s)}}},{key:"fireFetchData",value:function(){this.props.onFetchData(this.getResolvedState(),this)}},{key:"getPropOrState",value:function(e){return s.default.getFirstDefined(this.props[e],this.state[e])}},{key:"getStateOrProp",value:function(e){return s.default.getFirstDefined(this.state[e],this.props[e])}},{key:"filterData",value:function(e,t,r,n){var a=this,i=e;return t.length&&(i=(i=t.reduce((function(e,t){var a=n.find((function(e){return e.id===t.id}));if(!a||!1===a.filterable)return e;var o=a.filterMethod||r;return a.filterAll?o(t,e,a):e.filter((function(e){return o(t,e,a)}))}),i)).map((function(e){return e[a.props.subRowsKey]?o({},e,c({},a.props.subRowsKey,a.filterData(e[a.props.subRowsKey],t,r,n))):e})).filter((function(e){return!e[a.props.subRowsKey]||e[a.props.subRowsKey].length>0}))),i}},{key:"sortData",value:function(e,t){var r=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.length)return e;var a=(this.props.orderByMethod||s.default.orderBy)(e,t.map((function(e){return n[e.id]?function(t,r){return n[e.id](t[e.id],r[e.id],e.desc)}:function(t,n){return r.props.defaultSortMethod(t[e.id],n[e.id],e.desc)}})),t.map((function(e){return!e.desc})),this.props.indexKey);return a.forEach((function(e){e[r.props.subRowsKey]&&(e[r.props.subRowsKey]=r.sortData(e[r.props.subRowsKey],t,n))})),a}},{key:"getMinRows",value:function(){return s.default.getFirstDefined(this.props.minRows,this.getStateOrProp("pageSize"))}},{key:"onPageChange",value:function(e){var t=this.props,r=t.onPageChange,n=t.collapseOnPageChange,a={page:e};n&&(a.expanded={}),this.setStateWithData(a,(function(){r&&r(e)}))}},{key:"onPageSizeChange",value:function(e){var t=this.props.onPageSizeChange,r=this.getResolvedState(),n=r.pageSize*r.page,a=Math.floor(n/e);this.setStateWithData({pageSize:e,page:a},(function(){t&&t(e,a)}))}},{key:"sortColumn",value:function(e,t){var r=this.getResolvedState(),n=r.sorted,a=r.skipNextSort,o=r.defaultSortDesc,i=e.hasOwnProperty("defaultSortDesc")?e.defaultSortDesc:o,l=!i;if(a)this.setStateWithData({skipNextSort:!1});else{var u=this.props.onSortedChange,c=s.default.clone(n||[]).map((function(e){return e.desc=s.default.isSortingDesc(e),e}));if(s.default.isArray(e))!function(){var r=c.findIndex((function(t){return t.id===e[0].id}));r>-1?(c[r].desc===l?t?c.splice(r,e.length):e.forEach((function(e,t){c[r+t].desc=i})):e.forEach((function(e,t){c[r+t].desc=l})),t||(c=c.slice(r,e.length))):c=t?c.concat(e.map((function(e){return{id:e.id,desc:i}}))):e.map((function(e){return{id:e.id,desc:i}}))}();else{var f=c.findIndex((function(t){return t.id===e.id}));if(f>-1){var d=c[f];d.desc===l?t?c.splice(f,1):(d.desc=i,c=[d]):(d.desc=l,t||(c=[d]))}else t?c.push({id:e.id,desc:i}):c=[{id:e.id,desc:i}]}this.setStateWithData({page:!n.length&&c.length||!t?0:this.state.page,sorted:c},(function(){u&&u(c,e,t)}))}}},{key:"filterColumn",value:function(e,t){var r=this.getResolvedState().filtered,n=this.props.onFilteredChange,a=(r||[]).filter((function(t){if(t.id!==e.id)return!0}));""!==t&&a.push({id:e.id,value:t}),this.setStateWithData({filtered:a},(function(){n&&n(a,e,t)}))}},{key:"resizeColumnStart",value:function(e,t,r){var n=this;e.stopPropagation();var a=e.target.parentElement.getBoundingClientRect().width,o=void 0;o=r?e.changedTouches[0].pageX:e.pageX,this.trapEvents=!0,this.setStateWithData({currentlyResizing:{id:t.id,startX:o,parentWidth:a}},(function(){r?(document.addEventListener("touchmove",n.resizeColumnMoving),document.addEventListener("touchcancel",n.resizeColumnEnd),document.addEventListener("touchend",n.resizeColumnEnd)):(document.addEventListener("mousemove",n.resizeColumnMoving),document.addEventListener("mouseup",n.resizeColumnEnd),document.addEventListener("mouseleave",n.resizeColumnEnd))}))}},{key:"resizeColumnMoving",value:function(e){e.stopPropagation();var t=this.props.onResizedChange,r=this.getResolvedState(),n=r.resized,a=r.currentlyResizing,o=n.filter((function(e){return e.id!==a.id})),i=void 0;"touchmove"===e.type?i=e.changedTouches[0].pageX:"mousemove"===e.type&&(i=e.pageX);var l=Math.max(a.parentWidth+i-a.startX,11);o.push({id:a.id,value:l}),this.setStateWithData({resized:o},(function(){t&&t(o,e)}))}},{key:"resizeColumnEnd",value:function(e){e.stopPropagation();var t="touchend"===e.type||"touchcancel"===e.type;t&&(document.removeEventListener("touchmove",this.resizeColumnMoving),document.removeEventListener("touchcancel",this.resizeColumnEnd),document.removeEventListener("touchend",this.resizeColumnEnd)),document.removeEventListener("mousemove",this.resizeColumnMoving),document.removeEventListener("mouseup",this.resizeColumnEnd),document.removeEventListener("mouseleave",this.resizeColumnEnd),t||this.setStateWithData({skipNextSort:!0,currentlyResizing:!1})}}]),t}(e)}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}var c=function(){return{}};t.default={data:[],loading:!1,showPagination:!0,showPaginationTop:!1,showPaginationBottom:!0,showPageSizeOptions:!0,pageSizeOptions:[5,10,20,25,50,100],defaultPageSize:20,showPageJump:!0,collapseOnSortingChange:!0,collapseOnPageChange:!0,collapseOnDataChange:!0,freezeWhenExpanded:!1,sortable:!0,resizable:!0,filterable:!1,defaultSortDesc:!1,defaultSorted:[],defaultFiltered:[],defaultResized:[],defaultExpanded:{},defaultFilterMethod:function(e,t,r){var n=e.pivotId||e.id;return void 0===t[n]||String(t[n]).startsWith(e.value)},defaultSortMethod:function(e,t,r){return t=null==t?"":t,(e="string"==typeof(e=null==e?"":e)?e.toLowerCase():e)>(t="string"==typeof t?t.toLowerCase():t)?1:ediv{position:absolute;display:block;text-align:center;width:100%;top:50%;left:0;font-size:15px;color:rgba(0,0,0,.6);-webkit-transform:translateY(-52%);transform:translateY(-52%);-webkit-transition:all .3s cubic-bezier(.25,.46,.45,.94);transition:all .3s cubic-bezier(.25,.46,.45,.94)}.ReactTable .-loading.-active{opacity:1;z-index:2;pointer-events:all}.ReactTable .-loading.-active>div{-webkit-transform:translateY(50%);transform:translateY(50%)}.ReactTable .rt-resizing .rt-td,.ReactTable .rt-resizing .rt-th{-webkit-transition:none!important;transition:none!important;cursor:col-resize;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}",""])},function(e,t){e.exports=function(e){var t="undefined"!=typeof window&&window.location;if(!t)throw new Error("fixUrls requires window.location");if(!e||"string"!=typeof e)return e;var r=t.protocol+"//"+t.host,n=r+t.pathname.replace(/\/[^\/]*$/,"/");return e.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,(function(e,t){var a,o=t.trim().replace(/^"(.*)"$/,(function(e,t){return t})).replace(/^'(.*)'$/,(function(e,t){return t}));return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(o)?e:(a=0===o.indexOf("//")?o:0===o.indexOf("/")?r+o:n+o.replace(/^\.\//,""),"url("+JSON.stringify(a)+")")}))}},function(e,t,r){var n=r(19);"string"==typeof n&&(n=[[e.i,n,""]]);var a={hmr:!0,transform:void 0,insertInto:void 0};r(7)(n,a);n.locals&&(e.exports=n.locals)},function(e,t,r){(e.exports=r(6)(!1)).push([e.i,'.ReactTable{height:100%;background-color:#fff}.rt-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.rt-th{font-weight:600}.rt-td,.rt-th{padding:7px 8px;overflow-wrap:break-word;max-width:100%;word-wrap:break-word}.rt-compact .rt-td,.rt-compact .rt-th{padding:4px 6px}.rt-nowrap .rt-td,.rt-nowrap .rt-th{white-space:nowrap;text-overflow:ellipsis}.rt-th-content{overflow:hidden;text-overflow:ellipsis}.rt-td-select{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.rt-select,.rt-td-select{display:-webkit-box;display:-ms-flexbox;display:flex}.rt-select{-webkit-box-align:center;-ms-flex-align:center;align-items:center}input[type=checkbox].rt-select-input,input[type=radio].rt-select-input{display:block;margin:0}.rt-align-left{text-align:left}.rt-align-right{text-align:right}.rt-align-center{text-align:center}.rt-table{border-width:1px;border-color:#e6e6e6}.rt-bordered .rt-table,.rt-outlined .rt-table{border-style:solid}.rt-th{border-bottom:2px solid #e6e6e6;border-left-width:1px;border-left-color:rgba(0,0,0,.05)}.rt-bordered .rt-th,.rt-outlined .rt-th{border-bottom-width:1px}.rt-td{border-top:1px solid #f2f2f2;border-left-width:1px;border-left-color:rgba(0,0,0,.05)}.rt-borderless .rt-td,.rt-tr-group:first-child>.rt-tr:first-child .rt-td{border-top:none}.rt-bordered .rt-td,.rt-bordered .rt-th{border-left-style:solid}.rt-bordered .rt-td:first-child,.rt-bordered .rt-th:first-child{border-left:none}.rt-th-group,.rt-th-group-none{border-bottom:none}.rt-th-group:after{content:"";position:absolute;margin:auto;left:8px;right:8px;bottom:0;width:100%;height:1px;background-color:#e6e6e6}.rt-bordered .rt-th-group:after,.rt-outlined .rt-th-group:after{left:0;right:0}.rt-tr-striped{background-color:rgba(0,0,0,.03)}.rt-tr-highlight:hover,.rt-tr-striped.rt-tr-highlight:hover{background-color:rgba(0,0,0,.05)}.rt-tr.-padRow{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ReactTable .rt-tbody{-ms-flex-negative:0;flex-shrink:0}@supports ((position:-webkit-sticky) or (position:sticky)){.ReactTable .rt-table{background:inherit}.ReactTable .rt-tbody{overflow:visible}.ReactTable .rt-thead.-header{top:0}.ReactTable .rt-tfoot,.ReactTable .rt-thead.-header{position:-webkit-sticky;position:sticky;background:inherit;z-index:2}.ReactTable .rt-tfoot{bottom:0}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){.ReactTable .rt-tbody{overflow:auto;-ms-overflow-style:-ms-autohiding-scrollbar}}.rt-td-filter{border-top:0;border-bottom:1px solid #f2f2f2}.rt-borderless .rt-td-filter{border-bottom:0}.rt-filter{padding:5px 7px;color:inherit;background-color:#fff;border:1px solid rgba(0,0,0,.1);border-radius:3px;font-family:inherit;font-size:inherit;font-weight:400;outline-width:0;outline-style:solid}.rt-filter:focus{border:1px solid rgba(0,0,0,.25)}.rt-sort-header{display:-webkit-box;display:-ms-flexbox;display:flex}.rt-align-center .rt-sort-header{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.rt-align-right .rt-sort-header{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.rt-th{outline-width:0;outline-style:solid}.rt-th[aria-sort] .rt-sort-left:after{padding-right:5px;line-height:0}.rt-th[aria-sort] .rt-sort-right:after{padding-left:5px;line-height:0}.rt-th[aria-sort=ascending] .rt-sort-left:after,.rt-th[aria-sort=ascending] .rt-sort-right:after{content:"\\2191"}.rt-th[aria-sort=descending] .rt-sort-left:after,.rt-th[aria-sort=descending] .rt-sort-right:after{content:"\\2193"}.rt-th[aria-sort=none] .rt-sort:after{content:"\\2195";opacity:.4}.rt-th[data-sort-hint=ascending] .rt-sort-left:after,.rt-th[data-sort-hint=ascending] .rt-sort-right:after{content:"\\2191";opacity:.4}.rt-th[data-sort-hint=descending] .rt-sort-left:after,.rt-th[data-sort-hint=descending] .rt-sort-right:after{content:"\\2193";opacity:.4}.rt-expander-button{margin:0 2px;padding:0;background:none;border:none;cursor:pointer}.rt-expander{display:inline-block;position:relative;padding:0 8px;color:transparent;outline-width:0;outline-style:solid}.rt-expander:after{content:"";position:absolute;width:0;height:0;top:50%;left:50%;-webkit-transform:translate(-50%,-50%) rotate(-90deg);transform:translate(-50%,-50%) rotate(-90deg);border-left:5.04px solid transparent;border-right:5.04px solid transparent;border-top:7px solid rgba(0,0,0,.8);-webkit-transition:all .3s cubic-bezier(.175,.885,.32,1.275);transition:all .3s cubic-bezier(.175,.885,.32,1.275);cursor:pointer}.rt-expander.-open:after{-webkit-transform:translate(-50%,-50%) rotate(0);transform:translate(-50%,-50%) rotate(0)}.rt-pagination{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:6px 4px;border-top:1px solid #f2f2f2}.rt-bordered .rt-pagination,.rt-outlined .rt-pagination{border-top:none}.rt-pagination-info :not(:last-child){margin-right:16px}.rt-page-info{display:inline-block;margin:6px 8px;opacity:.9}.rt-page-size{display:inline-block;margin:0 8px}.rt-page-size-select{margin:0 2px}.rt-page-button,.rt-page-jump,.rt-page-size-select{font-family:inherit;font-size:inherit;color:inherit;line-height:inherit}.rt-page-jump,.rt-page-size-select{background-color:#fff;padding:3px;border-radius:3px;border:1px solid rgba(0,0,0,.05)}@supports (-moz-appearance:none){.rt-page-size-select{-moz-appearance:none;padding-right:12px;background-image:url(\'data:image/svg+xml;charset=US-ASCII,\');background-repeat:no-repeat;background-position:right 6px center;background-size:6px}}.rt-page-button{padding:6px 12px;background-color:transparent;border:none;border-radius:3px;outline-width:0;outline-style:solid;cursor:pointer}.rt-page-button::-moz-focus-inner{padding:0;border-style:none}.rt-page-button:disabled{opacity:.6;cursor:default}.rt-page-button:hover{background-color:rgba(0,0,0,.04)}.rt-page-button:active{background-color:rgba(0,0,0,.08)}.rt-keyboard-active .rt-page-button:focus{background-color:rgba(0,0,0,.04)}.rt-page-button:disabled:focus,.rt-page-button:disabled:hover{background-color:transparent}.rt-page-button-current{font-weight:700}.rt-page-ellipsis{margin:0 4px;pointer-events:none}.rt-page-numbers{display:inline-block;margin:0 8px;white-space:nowrap}.rt-page-jump{width:70px;text-align:center}.rt-tbody-noData{position:relative}.rt-tbody-noData .rt-td{border-color:transparent}.rt-noData{display:block;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);line-height:0;z-index:1}.rt-search{display:block;-ms-flex-item-align:end;align-self:flex-end;margin-bottom:8px;padding:5px 7px;color:inherit;background-color:#fff;border:1px solid rgba(0,0,0,.1);border-radius:3px;outline-width:0;outline-style:solid;font-family:inherit;font-size:inherit}.rt-search:active,.rt-search:focus{border:1px solid rgba(0,0,0,.25)}',""])},function(e,t,r){"use strict";r.r(t);var n=r(3),a=r(1),o=r.n(a),i=r(2),l=r.n(i),s=r(0),u=r.n(s);function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function f(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var d=function(e){for(var t=1;tn&&(n=(t=t.trim()).charCodeAt(0)),n){case 38:return t.replace(h,"$1"+e.trim());case 58:return e.trim()+t.replace(h,"$1"+e.trim());default:if(0<1*r&&0s.charCodeAt(8))break;case 115:i=i.replace(s,"-webkit-"+s)+";"+i;break;case 207:case 102:i=i.replace(s,"-webkit-"+(102l.charCodeAt(0)&&(l=l.trim()),l=[l],0p)&&(L=(B=B.replace(" ",":")).length),0=4;++n,a-=4)t=1540483477*(65535&(t=255&e.charCodeAt(n)|(255&e.charCodeAt(++n))<<8|(255&e.charCodeAt(++n))<<16|(255&e.charCodeAt(++n))<<24))+(59797*(t>>>16)<<16),r=1540483477*(65535&(t^=t>>>24))+(59797*(t>>>16)<<16)^1540483477*(65535&r)+(59797*(r>>>16)<<16);switch(a){case 3:r^=(255&e.charCodeAt(n+2))<<16;case 2:r^=(255&e.charCodeAt(n+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(n)))+(59797*(r>>>16)<<16)}return(((r=1540483477*(65535&(r^=r>>>13))+(59797*(r>>>16)<<16))^r>>>15)>>>0).toString(36)},w={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};var x=/[A-Z]|^ms/g,S=/_EMO_([^_]+?)_([^]*?)_EMO_/g,P=function(e){return 45===e.charCodeAt(1)},C=function(e){return null!=e&&"boolean"!=typeof e},O=function(e){var t={};return function(r){return void 0===t[r]&&(t[r]=e(r)),t[r]}}((function(e){return P(e)?e:e.replace(x,"-$&").toLowerCase()})),k=function(e,t){switch(e){case"animation":case"animationName":if("string"==typeof t)return t.replace(S,(function(e,t,r){return j={name:t,styles:r,next:j},t}))}return 1===w[e]||P(e)||"number"!=typeof t||0===t?t:t+"px"};function T(e,t,r,n){if(null==r)return"";if(void 0!==r.__emotion_styles)return r;switch(typeof r){case"boolean":return"";case"object":if(1===r.anim)return j={name:r.name,styles:r.styles,next:j},r.name;if(void 0!==r.styles){var a=r.next;if(void 0!==a)for(;void 0!==a;)j={name:a.name,styles:a.styles,next:j},a=a.next;return r.styles+";"}return function(e,t,r){var n="";if(Array.isArray(r))for(var a=0;ae.length)&&(t=e.length);for(var r=0,n=new Array(t);r'+'\')')}}),".rt-page-button":B({},q),".rt-page-button:not(:disabled):hover":B({},X),".rt-page-button:not(:disabled):active":B({},Y),".rt-keyboard-active & .rt-page-button:not(:disabled):focus":B({},X),".rt-page-button-current":B({},Z)})};return function e(t){for(var r=0,n=Object.entries(t);r1&&void 0!==arguments[1]?arguments[1]:{};if(!e||!t)return e;var r=Object.keys(t),n="("+r.map((function(e){return"{".concat(e,"}")})).join("|")+")",a=e.split(new RegExp(n)),o=r.reduce((function(e,r){return e["{".concat(r,"}")]=t[r],e}),{}),i=a.map((function(e){return null!=o[e]?o[e]:e}));return i.some((function(e){return"object"===J(e)}))?i:i.join("")}function X(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function Y(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var he=function(e){var t=e.isCurrent,r=e.className,n=ge(e,["isCurrent","className"]);return r=Q(r,"rt-page-button",t?" rt-page-button-current":null),o.a.createElement("button",pe({type:"button",className:r},n),n.children)};var me=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&ie(e,t)}(l,e);var t,r,n,a,i=(t=l,function(){var e,r=ce(t);if(ue()){var n=ce(this).constructor;e=Reflect.construct(r,arguments,n)}else e=r.apply(this,arguments);return le(this,e)});function l(e){var t;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,l),(t=i.call(this,e)).changePage=t.changePage.bind(se(t)),t.applyPage=t.applyPage.bind(se(t)),t.state={pageJumpValue:e.page+1,prevPage:e.page},t}return r=l,a=[{key:"getDerivedStateFromProps",value:function(e,t){return e.page!==t.prevPage?{pageJumpValue:e.page+1,prevPage:e.page}:null}}],(n=[{key:"changePage",value:function(e){e!==this.props.page+1&&this.props.onPageChange(e-1)}},{key:"applyPage",value:function(e){e&&e.preventDefault();var t=this.state.pageJumpValue;if(""!==t)this.changePage(t);else{var r=this.props.page+1;this.setState({pageJumpValue:r})}}},{key:"renderPageInfo",value:function(e){var t=e.page,r=e.pageSize,n=e.sortedData,a=e.language,i=n.length,l=Math.min(t*r+1,n.length),s=Math.min(t*r+r,n.length),u=q(a.pageInfo,{rowStart:l,rowEnd:s,rows:i});return o.a.createElement("div",{className:"rt-page-info"},u)}},{key:"renderPageSizeOptions",value:function(e){var t=e.pageSize,r=e.pageSizeOptions,n=e.onPageSizeChange,a=e.language,i=o.a.createElement("select",{key:"page-size-select",className:"rt-page-size-select","aria-label":a.pageSizeOptionsLabel,onChange:function(e){return n(Number(e.target.value))},value:t},r.map((function(e,t){return o.a.createElement("option",{key:t,value:e},e)}))),l=q(a.pageSizeOptions,{rows:i});return o.a.createElement("div",{className:"rt-page-size"},l)}},{key:"renderPageJump",value:function(e){var t=e.onChange,r=e.value,n=e.onBlur,a=e.onKeyPress,i=e.inputType,l=e.language;return o.a.createElement("input",{key:"page-jump",className:"rt-page-jump","aria-label":l.pageJumpLabel,type:i,onChange:t,value:r,onBlur:n,onKeyPress:a})}},{key:"getPageJumpProperties",value:function(){var e=this;return{onKeyPress:function(t){13!==t.which&&13!==t.keyCode||e.applyPage()},onBlur:this.applyPage,value:this.state.pageJumpValue,onChange:function(t){var r=t.target.value;if(""!==r){var n=Number(r);if(!Number.isNaN(n)){var a=Math.min(Math.max(n,1),Math.max(e.props.pages,1));e.setState({pageJumpValue:a})}}else e.setState({pageJumpValue:r})},inputType:"number",language:this.props.language}}},{key:"render",value:function(){var e=this,t=this.props,r=t.autoHidePagination,n=t.paginationType,a=t.showPageSizeOptions,i=t.showPageInfo,l=t.page,s=t.pages,u=t.canPrevious,c=t.canNext,f=t.className,d=t.style,p=t.theme,g=t.language;if(r){var h=this.props,m=h.defaultPageSize,b=h.pageSizeOptions,y=h.resolvedData,v=a?Math.min.apply(Math,[m].concat(fe(b))):m;if(y.length<=v)return null}var w,x=i?this.renderPageInfo(this.props):null,S=a?this.renderPageSizeOptions(this.props):null,P=l+1,C=function(e,t){return t<=6?fe(Array(t)).map((function(e,t){return t+1})):e<=4?[1,2,3,4,5,t]:t-e<3?[1,t-3,t-2,t-1,t]:[1,e-1,e,e+1,t]}(P,s);if("numbers"===n){var O=[];C.forEach((function(t,r){var n=P===t,a=o.a.createElement(he,{key:t,isCurrent:n,onClick:e.changePage.bind(null,t),"aria-label":q(g.pageNumberLabel,{page:t})+(n?" ":""),"aria-current":n?"page":null},t);t-C[r-1]>1&&O.push(o.a.createElement("span",{className:"rt-page-ellipsis",key:"ellipsis-".concat(t),role:"separator"},"...")),O.push(a)})),w=O}else{var k="jump"===n?this.renderPageJump(this.getPageJumpProperties()):P,T=Math.max(s,1);w=o.a.createElement("div",{className:"rt-page-numbers"},q(g.pageNumbers,{page:k,pages:T}))}var j=o.a.createElement(he,{className:"rt-prev-button",onClick:function(){u&&e.changePage(P-1)},disabled:!u,"aria-disabled":u?null:"true","aria-label":g.pagePreviousLabel},g.pagePrevious),E=o.a.createElement(he,{className:"rt-next-button",onClick:function(){c&&e.changePage(P+1)},disabled:!c,"aria-disabled":c?null:"true","aria-label":g.pageNextLabel},g.pageNext);return o.a.createElement("div",{className:Q(f,"rt-pagination",V(p.paginationStyle)),style:d},o.a.createElement("div",{className:"rt-pagination-info"},x,S),o.a.createElement("div",{className:"rt-pagination-nav"},j,w,E))}}])&&oe(r.prototype,n),a&&oe(r,a),l}(o.a.Component);function be(e){return(be="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ye(){return(ye=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}function Ce(e,t){for(var r=0;re.length)&&(t=e.length);for(var r=0,n=new Array(t);r1?" (".concat(t[e],")"):"")})).join(", ")}};function He(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3;if(!Number.isFinite(e))return e;t=t>0?t:0;var r=Math.pow(10,t);return Math.sign(e)*Math.round(Math.abs(e)*r)/r}function Ge(e){return e.map(Ue).filter((function(e){return"number"==typeof e}))}function Ue(e){return(null==e||void 0===e||Ve(e))&&(e=null),"Inf"===e&&(e=1/0),"-Inf"===e&&(e=-1/0),"string"==typeof e&&(e=Number(e)),e}function Ve(e){return"NA"===e||"NaN"===e}function Je(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function $e(e){for(var t=1;t=e.length?{done:!0}:{done:!1,value:e[t++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,a,o=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return o=e.done,e},e:function(e){i=!0,a=e},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw a}}}}function Ye(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r0&&void 0!==arguments[0]?arguments[0]:{},t=e.type,r=e.naLast;return function(e,n,a){return"numeric"===t?(e=Ue(e),n=Ue(n)):(e="string"==typeof e?e.toLowerCase():e,n="string"==typeof n?n.toLowerCase():n),e===n?0:null==e?r?a?-1:1:-1:null==n?r?a?1:-1:1:e>n?1:ee.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}function st(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ut(e,t){for(var r=0;r1&&t.preventDefault(),e.setState({clicked:!0})},onFocus:function(){e.state.clicked||o||i||e.setState({showFocus:!0})},onBlur:function(){e.setState({showFocus:!1,clicked:!1})},tabIndex:"0","data-sort-hint":this.state.showFocus?n:void 0})}return Ft(l)}}]),r}(o.a.Component);Object.assign(i.ReactTableDefaults,{ThComponent:Mt});var It=function(e){return{state:e}},Lt=i.ReactTableDefaults.TbodyComponent,Wt=i.ReactTableDefaults.NoDataComponent;Object.assign(i.ReactTableDefaults,{TbodyComponent:function(e){var t=e.state,r=e.className,n=e.children,a=lt(e,["state","className","children"]),i=t.pageRows,l=t.theme,s=t.language,u=!i.length&&o.a.createElement(Wt,null,s.noData);return r=u?Q(r,"rt-tbody-noData"):r,r=Q(r,V(l.tableBodyStyle)),o.a.createElement(Lt,yt({role:"rowgroup",className:r},a),n,u)},NoDataComponent:function(){return null}}),Object.assign(i.ReactTableDefaults,{FilterComponent:function(e){var t=e.column,r=e.filter,n=e.onChange,a=t.name,i=t.theme,l=t.language;return o.a.createElement("input",{type:"text",className:Q("rt-filter",V(i.filterInputStyle)),style:{width:"100%"},value:r?r.value:"",onChange:function(e){return n(e.target.value)},placeholder:l.filterPlaceholder,"aria-label":q(l.filterLabel,{name:a})})}}),Object.assign(i.ReactTableDefaults,{ExpanderComponent:function(e){var t=e.isExpanded,r=e.column,n=r.theme,a=r.language,i=t?a.detailsCollapseLabel:a.detailsExpandLabel;return o.a.createElement("button",{className:"rt-expander-button","aria-label":i},o.a.createElement("span",{className:Q("rt-expander",t&&"-open",V(n.expanderStyle)),tabIndex:"-1","aria-hidden":"true"},"•"))}});var Kt=i.ReactTableDefaults.LoadingComponent;Object.assign(i.ReactTableDefaults,{LoadingComponent:function(e){var t=e.loading,r=lt(e,["loading"]);return t?Kt(wt({loading:t},r)):null}}),l.a.propTypes=d,l.a.prototype.oldComponentWillReceiveProps=l.a.prototype.UNSAFE_componentWillReceiveProps,l.a.prototype.UNSAFE_componentWillReceiveProps=function(e,t){var r=this;e=wt({},e),this.props.dataKey&&this.props.dataKey===e.dataKey&&(e.data=this.props.data,e.columns=this.props.columns);return["pivotBy","sorted","filtered"].forEach((function(t){JSON.stringify(r.props[t])===JSON.stringify(e[t])&&(e[t]=r.props[t])})),this.props.searchable!==e.searchable&&(e.filtered=this.state.filtered.filter((function(e){return e.id!==r.props.searchKey}))),this.oldComponentWillReceiveProps(e,t)},l.a.prototype.oldFilterData=l.a.prototype.filterData,l.a.prototype.filterData=function(e,t,r,n){var a=n;if(this.props.searchable){var o=n.filter((function(e){return e.createMatcher})),i={id:this.props.searchKey,filterAll:!0,filterable:!0,filterMethod:function(e,t){if(!e.value)return t;var r=o.reduce((function(t,r){return t[r.id]=r.createMatcher(e.value),t}),{});return t=t.filter((function(e){if(e._subRows)return!0;var t,n=function(e){if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(e=at(e))){var t=0,r=function(){};return{s:r,n:function(){return t>=e.length?{done:!0}:{done:!1,value:e[t++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,a,o=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return o=e.done,e},e:function(e){i=!0,a=e},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw a}}}}(o);try{for(n.s();!(t=n.n()).done;){var a=t.value,i=e._original[a.id];if(r[a.id](i))return!0}}catch(e){n.e(e)}finally{n.f()}}))}};a=a.concat(i)}if(this.props.crosstalkGroup){var l={id:this.props.crosstalkId,filterAll:!0,filterable:!0,filterMethod:function(e,t){return e.value?t=t.filter((function(t){return!!t._subRows||(!!e.value.includes(t._index)||void 0)})):t}};a=a.concat(l)}return this.oldFilterData(e,t,r,a)};var Bt,Ht,Gt,Ut=function(e){var t=e.searchValue,r=e.onSearchChange,n=e.searchPlaceholder,l=e.searchLabel,s=e.searchClassName,u=lt(e,["searchValue","onSearchChange","searchPlaceholder","searchLabel","searchClassName"]),c=o.a.createElement("input",{type:"text",value:t,onChange:r,className:Q("rt-search",s),placeholder:n,"aria-label":l});return o.a.createElement(a.Fragment,null,c,o.a.createElement(i.ReactTableDefaults.TableComponent,u))},Vt=(Bt=l.a,(Gt=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Oe(e,t)}(l,e);var t,r,n,a,i=(t=l,function(){var e,r=je(t);if(Te()){var n=je(this).constructor;e=Reflect.construct(r,arguments,n)}else e=r.apply(this,arguments);return ke(this,e)});function l(e){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,l),i.call(this,e)}return r=l,(n=[{key:"rowSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.toggleSelection,a=t.selectType,i=t.SelectInputComponent,l=t.language,s=r(e.index),u={checked:s,onClick:n,selectType:a,row:e.row,label:s?l.deselectRowLabel:l.selectRowLabel};return o.a.createElement(i,u)}},{key:"subRowSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.toggleAll,a=t.selectType,i=t.SelectInputComponent,l=t.language;if("radio"===a)return null;var s=e.subRows;if(!s||s.some((function(e){return e._aggregated})))return null;var u=s.every((function(e){return r(e._index)})),c={checked:u,onClick:n,selectType:a,rows:s,label:u?l.deselectAllSubRowsLabel:l.selectAllSubRowsLabel};return o.a.createElement(i,c)}},{key:"headSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.selectType,a=t.toggleAll,i=t.SelectAllInputComponent,l=t.language;if("radio"===n)return null;var s=e.data;if(0===s.length||s.some((function(e){return e._aggregated})))return null;var u=s.every((function(e){return r(e._index)})),c={checked:u,onClick:a,selectType:n,rows:s,label:u?l.deselectAllRowsLabel:l.selectAllRowsLabel};return o.a.createElement(i,c)}},{key:"render",value:function(){for(var e=this,t=this.props,r=t.columns,n=t.selectWidth,a=t.forwardedRef,i=Pe(t,["columns","selectWidth","forwardedRef"]),l=this.props,s=l.isSelected,u=l.selectType,c=l.toggleAll,f=l.toggleSelection,d=l.selectId,p={},g=0;g1&&void 0!==arguments[1])||arguments[1];this.setState({selected:new Set(e)},(function(){return t.onSelectedChange(r)}))}},{key:"onSelectedChange",value:function(){var e=this,t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],r=this.props,n=r.selection,a=r.selectionId;if(n&&a&&window.Shiny){var o=nt(this.state.selected).map((function(e){return e+1}));window.Shiny.onInputChange(a,o)}if(this.ctSelection&&t){var i=nt(this.state.selected).map((function(t){return e.props.crosstalkKey[t]}));this.ctSelection.set(i)}}},{key:"toggleExpand",value:function(e,t){var r=wt({},this.state.expanded);if(t){var n=te(r,e.nestingPath);r=n&&n===t.id?re(r,e.nestingPath,void 0):re(r,e.nestingPath,t.id)}else{var a=te(r,e.nestingPath);r=re(r,e.nestingPath,a?void 0:{})}this.setState({expanded:r})}},{key:"isExpanded",value:function(e){var t=te(this.state.expanded,e.nestingPath);return t&&t===e.column.id}},{key:"toggleExpandAll",value:function(){var e=this.tableInstance.current.state,t=e.columns,r=e.sortedData,n=t.find((function(e){return e.details})),a=function e(t){return t.reduce((function(t,r,a){return r._subRows?t[a]=e(r._subRows):t[a]=n?n.id:{},t}),{})}(r);this.setState({expanded:a})}},{key:"toggleCollapseAll",value:function(){this.setState({expanded:{}})}},{key:"getRowInfo",value:function(e){var t=this;return e&&this.props.selection?wt({selected:e.subRows&&"multiple"===this.props.selection?e.subRows.every((function(e){return t.isSelected(e._index)})):this.isSelected(e.index)},e):e}},{key:"onTableUpdate",value:function(){if(window.Shiny&&window.Shiny.onInputChange&&!this.props.nested){var e=this.tableElement.current,t=this.tableInstance.current;if(!e||!t)return;var r=e.parentElement.getAttribute("data-reactable-output");if(!r)return;var n={page:t.state.page+1,pageSize:t.state.pageSize,pages:t.state.pages,selected:nt(this.state.selected).map((function(e){return e+1}))};Object.keys(n).forEach((function(e){window.Shiny.onInputChange("".concat(r,"__reactable__").concat(e),n[e])}))}}},{key:"componentDidMount",value:function(){var e=this;if(this.state.selected.size>0&&this.onSelectedChange(),!0===this.state.expanded&&this.toggleExpandAll(),window.Shiny&&!this.props.nested){var t=this.tableElement.current.parentElement.getAttribute("data-reactable-output");if(t){window.Shiny.addCustomMessageHandler("__reactable__".concat(t),(function(t){null!=t.selected&&e.setSelection(t.selected),null!=t.expanded&&(t.expanded?e.toggleExpandAll():e.toggleCollapseAll()),null!=t.page&&e.tableInstance.current.onPageChange(t.page)}))}}this.onTableUpdate();var r=this.props,n=r.crosstalkKey,a=r.crosstalkGroup;if(a&&window.crosstalk){this.ctSelection=new window.crosstalk.SelectionHandle(a),this.ctFilter=new window.crosstalk.FilterHandle(a),this.ctSelected=null,this.ctFiltered=null;var o=n.reduce((function(e,t,r){return e[t]=r,e}),{}),i=this.tableInstance.current,l={id:i.props.crosstalkId},s=function(){var t,r=e.ctSelected&&e.ctSelected.length>0?e.ctSelected:null,n=e.ctFiltered,a=(t=r||n?r?n?r.filter((function(e){return n.includes(e)})):r:n:null)?t.map((function(e){return o[e]})):null;i.filterColumn(l,a)},u=function(t){e.ctSelected!==t&&(e.ctSelected=t,s())};this.ctSelection.on("change",(function(t){t.sender!==e.ctSelection?(u(t.value),e.setSelection([],!1)):u(null)})),this.ctFilter.on("change",(function(t){var r;t.sender!==e.ctFilter&&(r=t.value,e.ctFiltered!==r&&(e.ctFiltered=r,s()))}))}}},{key:"componentDidUpdate",value:function(e){var t=this.props,r=t.defaultSelected,n=t.defaultExpanded;if(e.defaultSelected!==r){var a=new Set(r);this.setState({selected:a},this.onSelectedChange)}if(e.defaultExpanded!==n)if(!0===n)this.toggleExpandAll();else{var o=n||{};this.setState({expanded:o})}}},{key:"componentWillUnmount",value:function(){this.ctSelection&&this.ctSelection.close(),this.ctFilter&&this.ctFilter.close()}},{key:"render",value:function(){var e=this,t=this.props,s=t.data,u=t.columns,c=t.columnGroups,f=t.pivotBy,d=t.sortable,p=t.resizable,g=t.filterable,h=t.searchable,m=t.defaultSortDesc,b=t.defaultSorted,y=t.defaultPageSize,v=t.pageSizeOptions,w=t.paginationType,x=t.showPagination,S=t.showPageSizeOptions,P=t.showPageInfo,C=t.minRows,O=t.selection,k=t.onClick,T=t.outlined,j=t.bordered,E=t.borderless,R=t.striped,N=t.highlight,A=t.compact,D=t.nowrap,z=t.showSortIcon,_=t.showSortable,F=t.className,M=t.style,I=t.rowClassName,L=t.rowStyle,W=t.inline,K=t.width,B=t.height,H=t.language,U=t.crosstalkGroup,J=t.crosstalkKey,q=t.dataKey,X=t.theme;for(var Y in F=Q(F,V((X=G(X)||{}).style)),H=wt({},$,{},H))H[Y]=H[Y]||null;s=function(e){for(var t=Object.keys(e),r=new Array(e[t[0]].length),n=0;n2&&void 0!==arguments[2]?arguments[2]:{},l=r.sortable,s=r.showSortIcon,u=r.showSortable,c=r.isExpanded,f=r.onExpanderClick,d=r.theme,p=r.language;return e=e.map((function(e){var t=$e({},e);if(t.id=t.accessor,t.accessor.includes(".")&&(t.accessor=function(e){return e[t.id]}),"string"==typeof t.aggregate&&Be[t.aggregate]){var r=t.aggregate;t.aggregate=Be[r]}t.sortMethod=Qe({type:t.type,naLast:t.sortNALast}),t.filterAll=!0,"numeric"===t.type?t.createMatcher=tt:t.createMatcher=rt,t.filterMethod=function(e,r){var n=e.id,a=t.createMatcher(e.value);return r.filter((function(e){var t=e[n];return void 0===t||(!!e._subRows||a(t))}))},"numeric"===t.type?t.align=t.align||"right":t.align=t.align||"left",t.Cell=function(e){var r,l,s=e.value,u=null==s||"numeric"===t.type&&Ve(s);return u&&(s=t.na),!u&&t.format&&t.format.cell&&(s=et(s,t.format.cell)),t.cell&&("function"==typeof t.cell&&(s=t.cell($e({},e,{value:s}))),t.cell instanceof Array&&!e.aggregated&&(s=t.cell[e.index])&&(s=Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.cell[e.index]))),null!=s&&""!==s||(s="​"),r=o.a.isValidElement(s)?s:t.html?o.a.createElement("div",{style:{display:"inline"},dangerouslySetInnerHTML:{__html:s}}):String(s),t.details&&(t.details instanceof Array&&null==t.details[e.index]||(l=i.ReactTableDefaults.ExpanderComponent($e({},e,{isExpanded:c(e)})))),l?o.a.createElement(o.a.Fragment,null,l,r):r},t.PivotValue=function(e){var r=t.Cell(e);return o.a.createElement("span",null,r," ",e.subRows&&"(".concat(e.subRows.length,")"))},t.Aggregated=function(e){var r=null!=e.value?e.value:"";return t.format&&t.format.aggregated&&(r=et(r,t.format.aggregated)),t.aggregated&&(r=t.aggregated($e({},e,{value:r}))),t.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):r},t.Header=function(e){var r,i=t.name;if(t.header&&(i="function"==typeof t.header?t.header(e):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.header)),r=o.a.isValidElement(i)?o.a.createElement("div",{className:"rt-th-content"},i):t.html?o.a.createElement("div",{className:"rt-th-content",dangerouslySetInnerHTML:{__html:i}}):o.a.createElement("span",{className:"rt-th-content"},null!=i?String(i):""),ee(t.sortable,l)&&s){var c=u?"rt-sort":"";return"right"===t.align?o.a.createElement("div",{className:"rt-sort-header"},o.a.createElement("span",{className:Q(c,"rt-sort-left"),"aria-hidden":"true"}),r):o.a.createElement("div",{className:"rt-sort-header"},r,o.a.createElement("span",{className:Q(c,"rt-sort-right"),"aria-hidden":"true"}))}return r},t.footer&&(t.Footer=function(e){var r;return r="function"==typeof t.footer?t.footer(e):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.footer),o.a.isValidElement(r)?r:t.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):null!=r?String(r):""});var g="rt-align-".concat(t.align);t.headerClassName=Q(g,t.headerClassName),t.footerClassName=Q(g,t.footerClassName);var h=t.className,m=t.style;return t.className=void 0,t.style=void 0,t.getProps=function(e,t,r){var n,a,o={};if(!t)return o;(n="function"==typeof h?h(t,r,e):h instanceof Array?h[t.index]:h,o.className=Q(g,n),m)&&((a="function"==typeof m?m(t,r,e):m instanceof Array?m[t.index]:m)&&(o.style=a));return r.details&&(r.details instanceof Array&&null==r.details[t.index]||t.aggregated||(o.className=Q("rt-expandable",o.className),null==t.row[r.id]&&(o.style=$e({},o.style,{textOverflow:"inherit"})),o.onClick=function(e,n){f(t,r),n&&n()})),o},t.theme=d,t.language=p,t})),t&&(e=Ze(e,t)).forEach((function(e){(null!=e.name||e.header)&&(e.Header=function(t){var r=e.name;return e.header&&(r="function"==typeof e.header?e.header(t):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},e.header)),o.a.isValidElement(r)?r:e.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):null!=r?String(r):""}),e.align=e.align||"center",e.headerClassName=Q("rt-align-".concat(e.align),e.headerClassName)})),e}(u,c,{sortable:d,showSortIcon:z,showSortable:_,isExpanded:this.isExpanded,onExpanderClick:this.toggleExpand,theme:X,language:H}),null!=C&&(C=Math.max(C,1)),F=Q(F,T?"rt-outlined":"",j?"rt-bordered":"",E?"rt-borderless":"",A?"rt-compact":"",W?" rt-inline":"",D?"rt-nowrap":""),M=wt({width:K,height:B},M);var Z=l.a,re={};O&&(Z=Vt,re={isSelected:this.isSelected,toggleSelection:this.toggleSelection,toggleAll:this.toggleSelectionAll,selectType:"multiple"===O?"checkbox":"radio"});var ne=null==x,ae=Rt;(R||N||O||I||L)&&(ae=function(t,r){r=e.getRowInfo(r);var n,a=Rt(t,r);(R&&r&&(a.className=Q(a.className,r.viewIndex%2?null:"rt-tr-striped")),N&&r&&(a.className=Q(a.className,"rt-tr-highlight")),r&&r.selected&&(a.className=Q(a.className,"rt-tr-selected")),I)&&(n="function"==typeof I?I(r,t):I instanceof Array?r&&I[r.index]:I,a.className=Q(a.className,n));return L&&(a.style="function"==typeof L?L(r,t):L instanceof Array?r&&L[r.index]:L),a});var oe,ie=u.reduce((function(e,t){return e.concat(t.columns?t.columns:t)}),[]);ie.some((function(e){return e.details}))?(oe=function(t){var i=te(e.state.expanded,t.nestingPath),l=ie.find((function(e){return e.id===i})),s=l.details,u=l.html,c={};if("function"==typeof s){var f=s(e.getRowInfo(t));u&&(c.html=f),c.children=f}else if(s instanceof Array){var d=s[t.index];if(null==d)return null;u&&(c.html=d),c.children=Object(n.hydrate)({Reactable:r,Fragment:a.Fragment,WidgetContainer:Me},d)}return o.a.createElement(Jt,yt({key:i},c))},u=[{expander:!0,show:!1}].concat(nt(u))):oe=null;var le,se=function(){Object.keys(e.state.expanded).length>0&&e.setState({expanded:{}})},ue=Nt;k&&("select"===k?k=function(t,r){if(t&&(!r.pivoted||!t.aggregated))if(t.aggregated){if("single"===O)return;var n=t.subRows;if(!n||n.some((function(e){return e._aggregated})))return null;var a=n.map((function(e){return e._index})),o=a.every((function(t){return e.isSelected(t)}));e.toggleSelectionAll(a,!o)}else e.toggleSelection(t.index)}:"expand"===k&&(k=function(t,r){if(t){var n=ie.find((function(e){return e.details}));if(t.aggregated)r.pivoted||e.toggleExpand(t);else if(n){var a=n.details;if(a instanceof Array&&null==a[t.index])return;e.toggleExpand(t,n)}}}),ue=function(e,t,r){return wt({},Nt(e,t),{onClick:function(n,a){k(t,r,e),a&&a()}})});var ce=St;return h&&(le=Ut,ce=function(e,t,r,n){var a=e.filtered.find((function(t){return t.id===e.searchKey})),o=a?a.value:"";return wt({},St(e),{searchValue:o,onSearchChange:function(t){n.filterColumn({id:e.searchKey},t.target.value)},searchPlaceholder:e.language.searchPlaceholder,searchLabel:e.language.searchLabel,searchClassName:V(e.theme.searchInputStyle)})}),o.a.createElement(Z,yt({data:s,columns:u,pivotBy:f||[],sortable:d,resizable:p,filterable:g,searchable:h,searchKey:"__search__",defaultSortDesc:m,defaultSorted:b,defaultPageSize:y,pageSizeOptions:v,showPagination:x,showPageSizeOptions:S,PaginationComponent:me,paginationType:w,autoHidePagination:ne,showPageInfo:P,minRows:C,collapseOnSortingChange:!0,collapseOnPageChange:!0,collapseOnDataChange:!1,className:F,style:M,expanded:this.state.expanded,onExpandedChange:function(t){e.setState({expanded:t})},onPageChange:se,onSortedChange:se,getTableProps:ce,getTheadGroupTrProps:Ot,getTheadGroupThProps:Ct,getTheadTrProps:kt,getTheadThProps:Pt,getTheadFilterTrProps:Tt,getTheadFilterThProps:jt,getTbodyProps:It,getTrGroupProps:Et,getTrProps:ae,getTdProps:ue,getTfootTrProps:At,getTfootTdProps:Dt,TableComponent:le,SubComponent:oe},re,{theme:X,language:H,crosstalkGroup:U,crosstalkKey:J,crosstalkId:"__crosstalk__",key:"".concat(y),dataKey:q,ref:this.tableInstance,getProps:function(){return e.onTableUpdate(),{ref:e.tableElement,onMouseDown:function(){e.tableElement.current.classList.remove("rt-keyboard-active")},onKeyDown:function(){e.tableElement.current.classList.add("rt-keyboard-active")},onKeyUp:function(t){9===(t.which||t.keyCode)&&e.tableElement.current.classList.add("rt-keyboard-active")}}}}))}}]),r}(o.a.Component);$t.defaultProps={sortable:!0,resizable:!1,showPageSizeOptions:!1,showSortIcon:!0};var qt=$t;Object(n.reactWidget)("reactable","output",{Reactable:qt})}]); +//# sourceMappingURL=reactable.js.map \ No newline at end of file diff --git a/docs/posts/2020-08-17-tidytuesday-2020-week-33/index.html b/docs/posts/2020-08-17-tidytuesday-2020-week-33/index.html new file mode 100644 index 00000000..31092fe4 --- /dev/null +++ b/docs/posts/2020-08-17-tidytuesday-2020-week-33/index.html @@ -0,0 +1,2695 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 Week 33 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 Week 33

    + + + +

    An animation of the main characters in Avatar

    +
    + + + +
    + +
    + +
    +

    Visualization

    +

     

    +
    +

    +
    +

    Things I learned

    +
      +
    • Really basic image manipulation with {magick}

    • +
    • That you can get away with not doing the data part of data visualization for TidyTuesday

    • +
    +

    Things to improve

    +
      +
    • Should’ve picked a better color to represent air for Aang.

    • +
    • Not sure why it looks like white grid lines are there. All my attempts at getting rid of them failed, so I’ve just concluded that they’re likely an optical illusion.

    • +
    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +library(magick)
    +library(gganimate)
    +
    +aang <- image_read("https://vignette.wikia.nocookie.net/avatar/images/a/ae/Aang_at_Jasmine_Dragon.png")
    +iroh <- image_read("https://vignette.wikia.nocookie.net/avatar/images/c/c1/Iroh_smiling.png")
    +sokka <- image_read("https://vignette.wikia.nocookie.net/avatar/images/c/cc/Sokka.png")
    +toph <- image_read("https://vignette.wikia.nocookie.net/avatar/images/4/46/Toph_Beifong.png")
    +
    +# Script by Georgios Karamanis adapted and wrapped into a function
    +# - from https://github.com/gkaramanis/aRt/blob/master/split-bar/points-portraits.R
    +img_to_df <- function(img, index) {
    +  
    +  img <- image_convert(img, colorspace = "gray")
    +  
    +  img_w <- image_info(img)$width
    +  img_h <- image_info(img)$height
    +  
    +  if (img_w >= img_h) {
    +    img <- image_resize(img, "120")
    +  } else {
    +    img <- image_resize(img, ("x120"))
    +  }
    +  
    +  img_array <- drop(as.integer(img[[1]]))
    +  rownames(img_array) <- 1:nrow(img_array)
    +  colnames(img_array) <- 1:ncol(img_array)
    +  
    +  as.data.frame.table(img_array) %>% 
    +    `colnames<-`(c("y", "x", "b")) %>% 
    +    mutate(
    +      across(everything(), as.numeric),
    +      bf = 1 - b / 255
    +    ) %>% 
    +    mutate(character_id = index)
    +}
    +
    +plot_data <- imap_dfr(list(aang, iroh, sokka, toph), ~img_to_df(.x, .y)) %>% 
    +  group_by(character_id) %>% 
    +  mutate(point_id = 1:n()) %>% 
    +  ungroup() %>% 
    +  mutate(across(contains("id"), as.factor))
    +
    +anim <- ggplot(plot_data) +
    +  geom_point(aes(x = x, y = y, size = bf, group = point_id, color = character_id),
    +             shape = 16, show.legend = FALSE) +
    +  scale_y_reverse() +
    +  scale_size_continuous(range = c(0, 4)) +
    +  scale_color_manual(values = c("#C0EDFF", "#B33000", "#206BA4", "#8B4513")) +
    +  coord_fixed(expand = FALSE) +
    +  theme_void() +
    +  theme(panel.grid = element_blank()) +
    +  transition_states(id)
    +
    +animate(anim, width = 12, height = 9, units = "in", res = 120)
    +
    +
    +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-08-17-tidytuesday-2020-week-33/preview.png b/docs/posts/2020-08-17-tidytuesday-2020-week-33/preview.png new file mode 100644 index 00000000..0b6dc190 Binary files /dev/null and b/docs/posts/2020-08-17-tidytuesday-2020-week-33/preview.png differ diff --git a/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday-2020-week-33_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday-2020-week-33_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday-2020-week-33_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday_2020_33.gif b/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday_2020_33.gif new file mode 100644 index 00000000..c7c56caf Binary files /dev/null and b/docs/posts/2020-08-17-tidytuesday-2020-week-33/tidytuesday_2020_33.gif differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-1.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-1.png new file mode 100644 index 00000000..9ad07039 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-1.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-2.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-2.png new file mode 100644 index 00000000..744c6942 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-2.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-3.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-3.png new file mode 100644 index 00000000..70cc5370 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-3.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-4.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-4.png new file mode 100644 index 00000000..afc44836 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-4.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-5.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-5.png new file mode 100644 index 00000000..dff53ee5 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-5.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-6.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-6.png new file mode 100644 index 00000000..ccff51f6 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-6.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-7.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-7.png new file mode 100644 index 00000000..5135230e Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-7.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-8.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-8.png new file mode 100644 index 00000000..7f55227e Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-8.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-9.png b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-9.png new file mode 100644 index 00000000..c3c611c8 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/figure-html5/code-9.png differ diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.css b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.css new file mode 100644 index 00000000..e3b3a00a --- /dev/null +++ b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.css @@ -0,0 +1,104 @@ +/* prefixed by https://autoprefixer.github.io (PostCSS: v7.0.23, autoprefixer: v9.7.3) */ + +.panelset { + width: 100%; + position: relative; + --panel-tabs-border-bottom: #ddd; + --panel-tab-foreground: currentColor; + --panel-tab-background: unset; + --panel-tab-active-foreground: currentColor; + --panel-tab-active-background: unset; + --panel-tab-hover-foreground: currentColor; + --panel-tab-hover-background: unset; + --panel-tab-active-border-color: currentColor; + --panel-tab-hover-border-color: currentColor; + --panel-tab-inactive-opacity: 0.5; + --panel-tab-font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; +} + +.panelset * { + box-sizing: border-box; +} + +.panelset .panel-tabs { + display: -webkit-box; + display: flex; + flex-wrap: wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + flex-direction: row; + -webkit-box-pack: start; + justify-content: start; + -webkit-box-align: center; + align-items: center; + overflow-y: visible; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding: 0 0 2px 0; + box-shadow: inset 0 -2px 0px var(--panel-tabs-border-bottom); +} + +.panelset .panel-tabs * { + -webkit-transition: opacity 0.5s ease; + transition: opacity 0.5s ease; +} + +.panelset .panel-tabs .panel-tab { + min-height: 50px; + display: -webkit-box; + display: flex; + -webkit-box-pack: center; + justify-content: center; + -webkit-box-align: center; + align-items: center; + padding: 0.5em 1em; + font-family: var(--panel-tab-font-family); + opacity: var(--panel-tab-inactive-opacity); + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + color: var(--panel-tab-foreground); + background-color: var(--panel-tab-background); + list-style: none; + z-index: 5; +} + +.panelset .panel-tabs .panel-tab > a { + color: currentColor; + text-decoration: none; +} + +.panelset .panel-tabs .panel-tab > a:focus { + outline: none; +} + +.panelset .panel-tabs .panel-tab:hover { + border-bottom-color: var(--panel-tab-hover-border-color); + color: var(--panel-tab-hover-foreground); + background-color: var(--panel-tab-hover-background); + opacity: 1; + cursor: pointer; + z-index: 10; +} + +.panelset .panel-tabs .panel-tab:focus { + outline: none; + color: var(--panel-tab-hover-foreground); + border-bottom-color: var(--panel-tab-hover-border-color); + background-color: var(--panel-tab-hover-background); +} + +.panelset .panel-tabs .panel-tab.panel-tab-active { + border-top-color: var(--panel-tab-active-border-color); + color: var(--panel-tab-active-foreground); + background-color: var(--panel-tab-active-background); + opacity: 1; +} + +.panelset .panel { + display: none; +} + +.panelset .panel-active { + display: block; +} diff --git a/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.js b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.js new file mode 100644 index 00000000..6cda4336 --- /dev/null +++ b/docs/posts/2020-09-06-fonts-for-graphs/2020-09-06-fonts-for-graphs_files/panelset-0.2.3/panelset.js @@ -0,0 +1,321 @@ +/* global slideshow */ +(function () { + const ready = function (fn) { + /* MIT License Copyright (c) 2016 Nuclei */ + /* https://github.com/nuclei/readyjs */ + const completed = () => { + document.removeEventListener('DOMContentLoaded', completed) + window.removeEventListener('load', completed) + fn() + } + if (document.readyState !== 'loading') { + setTimeout(fn) + } else { + document.addEventListener('DOMContentLoaded', completed) + window.addEventListener('load', completed) + } + } + + ready(function () { + [...document.querySelectorAll('.panel-name')] + .map(el => el.textContent.trim()) + + const panelIds = {} + + const uniquePanelId = (name) => { + name = encodeURIComponent(name.toLowerCase().replace(/[\s]/g, '-')) + if (Object.keys(panelIds).includes(name)) { + name += ++panelIds[name] + } else { + panelIds[name] = 1 + } + return name + } + + const identifyPanelName = (item) => { + let name = 'Panel' + + // If the item doesn't have a parent element, then we've already processed + // it, probably because we're in an Rmd, and it's been removed from the DOM + if (!item.parentElement) { + return + } + + // In R Markdown when header-attrs.js is present, we may have found a + // section header but the class attributes won't be duplicated on the tag + if ( + (item.tagName === 'SECTION' || item.classList.contains('section')) && + /^H[1-6]/.test(item.children[0].tagName) + ) { + name = item.children[0].textContent + item.classList.remove('panel-name') + item.removeChild(item.children[0]) + return name + } + + const nameDiv = item.querySelector('.panel-name') + if (!nameDiv) return name + + // In remarkjs the .panel-name span might be in a paragraph tag + // and if the

    is empty, we'll remove it + if ( + nameDiv.tagName === 'SPAN' && + nameDiv.parentNode.tagName === 'P' && + nameDiv.textContent === nameDiv.parentNode.textContent + ) { + name = nameDiv.textContent + item.removeChild(nameDiv.parentNode) + return name + } + + // If none of the above, remove the nameDiv and return the name + name = nameDiv.textContent + nameDiv.parentNode.removeChild(nameDiv) + return name + } + + const processPanelItem = (item) => { + const name = identifyPanelName(item) + if (!name) { + return null + } + return { name, content: item.children, id: uniquePanelId(name) } + } + + const getCurrentPanelFromUrl = (panelset) => { + const params = new URLSearchParams(window.location.search) + return params.get(panelset) + } + + const reflowPanelSet = (panels, idx) => { + const res = document.createElement('div') + res.className = 'panelset' + res.id = 'panelset' + (idx > 0 ? idx : '') + const panelSelected = getCurrentPanelFromUrl(res.id) + + // create header row + const headerRow = document.createElement('ul') + headerRow.className = 'panel-tabs' + headerRow.setAttribute('role', 'tablist') + panels + .map((p, idx) => { + const panelHeaderItem = document.createElement('li') + panelHeaderItem.className = 'panel-tab' + panelHeaderItem.setAttribute('role', 'tab') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + if (thisPanelIsActive) { + panelHeaderItem.classList.add('panel-tab-active') + panelHeaderItem.setAttribute('aria-selected', true) + } + panelHeaderItem.tabIndex = 0 + panelHeaderItem.id = res.id + '_' + p.id // #panelsetid_panelid + + const panelHeaderLink = document.createElement('a') + panelHeaderLink.href = '?' + res.id + '=' + p.id + '#' + panelHeaderItem.id + panelHeaderLink.setAttribute('onclick', 'return false;') + panelHeaderLink.tabIndex = -1 // list item is tabable, not link + panelHeaderLink.innerHTML = p.name + panelHeaderLink.setAttribute('aria-controls', p.id) + + panelHeaderItem.appendChild(panelHeaderLink) + return panelHeaderItem + }) + .forEach(el => headerRow.appendChild(el)) + + res.appendChild(headerRow) + + panels + .map((p, idx) => { + const panelContent = document.createElement('section') + panelContent.className = 'panel' + panelContent.setAttribute('role', 'tabpanel') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + panelContent.classList.toggle('panel-active', thisPanelIsActive) + panelContent.id = p.id + panelContent.setAttribute('aria-labelledby', p.id) + Array.from(p.content).forEach(el => panelContent.appendChild(el)) + return panelContent + }) + .forEach(el => res.appendChild(el)) + + return res + } + + /* + * Update selected panel for panelset or delete panelset from query string + * + * @param panelset Panelset ID to update in the search params + * @param panel Panel ID of selected panel in panelset, or null to delete from search params + * @param params Current params object, or params from window.location.search + */ + function updateSearchParams (panelset, panel, params = new URLSearchParams(window.location.search)) { + if (panel) { + params.set(panelset, panel) + } else { + params.delete(panelset) + } + return params + } + + /* + * Update the URL to match params + */ + const updateUrl = (params) => { + if (typeof params === 'undefined') return + params = params.toString() ? ('?' + params.toString()) : '' + const { pathname, hash } = window.location + const uri = pathname + params + hash + window.history.replaceState(uri, '', uri) + } + + const togglePanel = (clicked) => { + if (clicked.nodeName.toUpperCase() === 'A') { + clicked = clicked.parentElement + } + if (!clicked.classList.contains('panel-tab')) return + if (clicked.classList.contains('panel-tab-active')) return + + const tabs = clicked.parentNode + .querySelectorAll('.panel-tab') + const panels = clicked.parentNode.parentNode + .querySelectorAll('.panel') + const panelTabClicked = clicked.children[0].getAttribute('aria-controls') + const panelClicked = clicked.parentNode.parentNode.id + + Array.from(tabs) + .forEach(t => { + t.classList.remove('panel-tab-active') + t.removeAttribute('aria-selected') + }) + Array.from(panels) + .forEach(p => { + const active = p.id === panelTabClicked + p.classList.toggle('panel-active', active) + // make inactive panels inaccessible by keyboard navigation + if (active) { + p.removeAttribute('tabIndex') + p.removeAttribute('aria-hidden') + } else { + p.setAttribute('tabIndex', -1) + p.setAttribute('aria-hidden', true) + } + }) + + clicked.classList.add('panel-tab-active') + clicked.setAttribute('aria-selected', true) + + // update query string + const params = updateSearchParams(panelClicked, panelTabClicked) + updateUrl(params) + } + + const initPanelSet = (panelset, idx) => { + let panels = Array.from(panelset.querySelectorAll('.panel')) + if (!panels.length && panelset.matches('.section[class*="level"]')) { + // we're in tabset-alike R Markdown + const panelsetLevel = [...panelset.classList] + .filter(s => s.match(/^level/))[0] + .replace('level', '') + + // move children that aren't inside a section up above the panelset + Array.from(panelset.children).forEach(function (el) { + if (el.matches('div.section[class*="level"]')) return + panelset.parentElement.insertBefore(el, panelset) + }) + + // panels are all .sections with .level + const panelLevel = +panelsetLevel + 1 + panels = Array.from(panelset.querySelectorAll(`.section.level${panelLevel}`)) + } + + if (!panels.length) return + + const contents = panels.map(processPanelItem).filter(o => o !== null) + const newPanelSet = reflowPanelSet(contents, idx) + panelset.parentNode.insertBefore(newPanelSet, panelset) + panelset.parentNode.removeChild(panelset) + + // click and touch events + const panelTabs = newPanelSet.querySelector('.panel-tabs'); + ['click', 'touchend'].forEach(eventType => { + panelTabs.addEventListener(eventType, function (ev) { + togglePanel(ev.target) + ev.stopPropagation() + }) + }) + panelTabs.addEventListener('touchmove', function (ev) { + ev.preventDefault() + }) + + // key events + newPanelSet + .querySelector('.panel-tabs') + .addEventListener('keydown', (ev) => { + const self = ev.currentTarget.querySelector('.panel-tab-active') + if (ev.code === 'Space' || ev.code === 'Enter') { + togglePanel(ev.target) + ev.stopPropagation() + } else if (ev.code === 'ArrowLeft' && self.previousSibling) { + togglePanel(self.previousSibling) + self.previousSibling.focus() + ev.stopPropagation() + } else if (ev.code === 'ArrowRight' && self.nextSibling) { + togglePanel(self.nextSibling) + self.nextSibling.focus() + ev.stopPropagation() + } + }) + + return panels + } + + // initialize panels + Array.from(document.querySelectorAll('.panelset')).map(initPanelSet) + + if (typeof slideshow !== 'undefined') { + const getVisibleActivePanelInfo = () => { + const slidePanels = document.querySelectorAll('.remark-visible .panel-tab-active') + + if (!slidePanels.length) return null + + return slidePanels.map(panel => { + return { + panel, + panelId: panel.children[0].getAttribute('aria-controls'), + panelSetId: panel.parentNode.parentNode.id + } + }) + } + + slideshow.on('hideSlide', slide => { + // clear focus if we had a panel-tab selected + document.activeElement.blur() + + // clear search query for panelsets in current slide + const params = [...document.querySelectorAll('.remark-visible .panelset')] + .reduce(function (params, panelset) { + return updateSearchParams(panelset.id, null, params) + }, new URLSearchParams(window.location.search)) + + updateUrl(params) + }) + + slideshow.on('afterShowSlide', slide => { + const slidePanels = getVisibleActivePanelInfo() + + if (slidePanels) { + // only first panel gets focus + slidePanels[0].panel.focus() + // but still update the url to reflect all active panels + const params = slidePanels.reduce( + function (params, { panelId, panelSetId }) { + return updateSearchParams(panelSetId, panelId, params) + }, + new URLSearchParams(window.location.search) + ) + updateUrl(params) + } + }) + } + }) +})() diff --git a/docs/posts/2020-09-06-fonts-for-graphs/index.html b/docs/posts/2020-09-06-fonts-for-graphs/index.html new file mode 100644 index 00000000..f371c7c4 --- /dev/null +++ b/docs/posts/2020-09-06-fonts-for-graphs/index.html @@ -0,0 +1,2679 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Fonts for graphs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + + + + +
    +

    Fonts for graphs

    + + + +

    A small collection of my favorite fonts for data visualization

    +
    + + + +
    +
    + +
    +

     

    +

    For the last few weeks I’ve been reading about and experimenting with fonts for data visualization in my spare time.1 Out of that, I have found a couple fonts that I really like and wanted to do a small showcase of them here.

    +

    These fonts are all free and available for download at Google Fonts.2 Note that not only are they all large font families that come with many different styles, you can also adjust various theme settings like lineheight in {ggplot2}, so what I’m showing here isn’t the full extent of what you can make with these fonts.

    +

     

    +
    +

    Arial

    +

    It’s the default. It’s dull. It’s just here for comparison.

    +

    +

    Montserrat

    +

    Simple design that can handle long lines of text. I like it for minimal plots.

    +

    +

    Roboto Mono

    +

    Monospaced member of the Roboto family. Very easy to read.

    +

    +

    Futura Bk BT

    +

    A slender and bold member of the Futura family. Looks nice even in larger sizes.

    +

    +

    Barlow

    +

    Also a slender font like Futura, but this has nicer ’j’s

    +

    +

    Adelle

    +

    A serif font that doesn’t go overboard. I use it a lot for short paragraphs.

    +

    +

    Merriweather

    +

    Similar to Adelle, but has a bit more pronounced hooks

    +

    +
    +

     

    +

    Misc.

    +

    Why spend 3 minutes copy-pasting code when you can spend an hour automatizing it?

    +

    This was my first time using dynamic Rmarkdown reporting. The plots above and the text descriptions that went with them were generated in a for loop, which I learned about here.

    +

    Here is the single chunk of code that made this possible:

    +
    +
    +
    library(ggplot2)
    +library(extrafont)
    +knitr::opts_chunk$set(fig.width = 7, dpi = 600)
    +
    +theme_set(theme_classic(base_size = 14))
    +
    +favorites <- c(
    +  "Arial" = "It's the default. It's dull. It's just here for comparison.",
    +  "Montserrat" = "Simple design that can handle long lines of text. I like it for minimal plots.",
    +  "Roboto Mono" = "Monospaced member of the Roboto family. Very easy to read.",
    +  "Futura Bk BT" = "A slender and bold member of the Futura family. Looks nice even in larger sizes.",
    +  "Barlow" = "Also a slender font like Futura, but this has nicer 'j's",
    +  "Adelle" = "A serif font that doesn't go overboard. I use it a lot for short paragraphs.",
    +  "Merriweather" = "Similar to Adelle, but has a bit more pronounced hooks"
    +)
    +
    +
    +for (font in names(favorites)) {
    +  cat("\n\n## ", font, "\n\n")
    +  cat("", favorites[font], "\n\n")
    +  plot <- qplot(data = mtcars, mpg, disp, color = factor(cyl)) +
    +    annotate("text", 28, 400, label = paste(letters, collapse = ''), family = font) +
    +    geom_curve(aes(x = 28, y = 380, xend = 22, yend = 260),
    +               color = 'black', curvature = -.3, arrow = arrow(), show.legend = FALSE) +
    +    labs(title = "This is an interesting plot title",
    +         subtitle = "Here's the subtitle 1234567890",
    +         caption = "This is the plot caption") +
    +    theme(text = element_text(family = font),
    +          plot.title.position = 'plot')
    +  print(plot)
    +}
    +
    +
    +
    +
    +
    +
    +
      +
    1. I reference a lot this great collection of fonts used in profesional visualization here.↩︎

    2. +
    3. For how to import local fonts into R to use for plotting, check out {extrafont} and/or {showtext}.↩︎

    4. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-06-fonts-for-graphs/preview.png b/docs/posts/2020-09-06-fonts-for-graphs/preview.png new file mode 100644 index 00000000..d35fa446 Binary files /dev/null and b/docs/posts/2020-09-06-fonts-for-graphs/preview.png differ diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.5/header-attrs.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.6/header-attrs.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.6/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/header-attrs-2.6/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.1/htmlwidgets.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.1/htmlwidgets.js new file mode 100644 index 00000000..6f3d672d --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.1/htmlwidgets.js @@ -0,0 +1,903 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval(code); + } catch(error) { + if (!error instanceof SyntaxError) { + throw error; + } + try { + result = eval("(" + code + ")"); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + if (cel) { + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + } + + return { + getWidth: function() { return cel.offsetWidth; }, + getHeight: function() { return cel.offsetHeight; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return el.offsetWidth; }, + getHeight: function() { return el.offsetHeight; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
    ").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var result = bindingDef.initialize(el, el.offsetWidth, + el.offsetHeight); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + initResult = binding.initialize(el, + sizeObj ? sizeObj.getWidth() : el.offsetWidth, + sizeObj ? sizeObj.getHeight() : el.offsetHeight + ); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + var resizeHandler = function(e) { + var size = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); + diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.2/htmlwidgets.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.2/htmlwidgets.js new file mode 100644 index 00000000..6f3d672d --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/htmlwidgets-1.5.2/htmlwidgets.js @@ -0,0 +1,903 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval(code); + } catch(error) { + if (!error instanceof SyntaxError) { + throw error; + } + try { + result = eval("(" + code + ")"); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + if (cel) { + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + } + + return { + getWidth: function() { return cel.offsetWidth; }, + getHeight: function() { return cel.offsetHeight; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return el.offsetWidth; }, + getHeight: function() { return el.offsetHeight; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
    ").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var result = bindingDef.initialize(el, el.offsetWidth, + el.offsetHeight); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + initResult = binding.initialize(el, + sizeObj ? sizeObj.getWidth() : el.offsetWidth, + sizeObj ? sizeObj.getHeight() : el.offsetHeight + ); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + var resizeHandler = function(e) { + var size = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); + diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/reactable-binding-0.2.0/reactable.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/reactable-binding-0.2.0/reactable.js new file mode 100644 index 00000000..308f474f --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/reactable-binding-0.2.0/reactable.js @@ -0,0 +1,7 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,r),a.l=!0,a.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)r.d(n,a,function(t){return e[t]}.bind(null,a));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=20)}([function(e,t,r){e.exports=r(13)()},function(e,t){e.exports=window.React},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ReactTableDefaults=void 0;var n=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,a=!1,o=void 0;try{for(var i,l=e[Symbol.iterator]();!(n=(i=l.next()).done)&&(r.push(i.value),!t||r.length!==t);n=!0);}catch(e){a=!0,o=e}finally{try{!n&&l.return&&l.return()}finally{if(a)throw o}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},a=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:[],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-1;return[t.map((function(t,i){o++;var l=a({},t,{_viewIndex:o}),s=r.concat([i]);if(l[U]&&u.default.get(re,s)){var c=e(l[U],s,o),f=n(c,2);l[U]=f[0],o=f[1]}return l})),o]}(Ae),Ie=n(Me,1);Ae=Ie[0];var Le=Z>0,We=Z+12&&void 0!==arguments[2]?arguments[2]:[],i={original:r[J],row:r,index:r[$],viewIndex:++Be,pageSize:Y,page:Z,level:o.length,nestingPath:o.concat([n]),aggregated:r[V],groupedByPivot:r[q],subRows:r[U]},c=u.default.get(re,i.nestingPath),f=P(He,i,void 0,e),d=u.default.splitProps(C(He,i,void 0,e));return l.default.createElement(se,a({key:i.nestingPath.join("_")},f),l.default.createElement(ue,a({className:d.className,style:d.style},d.rest),Oe.map((function(t,n){var o=te.find((function(e){return e.id===t.id}))||{},f="function"==typeof t.show?t.show():t.show,d=u.default.getFirstDefined(o.value,t.width,t.minWidth),p=u.default.getFirstDefined(o.value,t.width,t.maxWidth),g=u.default.splitProps(O(He,i,t,e)),h=u.default.splitProps(t.getProps(He,i,t,e)),m=[g.className,t.className,h.className],b=a({},g.style,t.style,h.style),y=a({},i,{isExpanded:c,column:a({},t),value:i.row[t.id],pivoted:t.pivoted,expander:t.expander,resized:te,show:f,width:d,maxWidth:p,tdProps:g,columnProps:h,classes:m,styles:b}),v=y.value,w=void 0,x=void 0,S=void 0,P=u.default.normalizeComponent(t.Cell,y,v),C=t.Aggregated||(t.aggregate?t.Cell:xe),k=t.Expander||ye,T=t.PivotValue||ve,j=we||function(e){return l.default.createElement("div",null,l.default.createElement(k,e),l.default.createElement(T,e))},E=t.Pivot||j;(y.pivoted||y.expander)&&(y.expandable=!0,w=!0,y.pivoted&&!y.subRows&&(y.expandable=!1,w=!1)),y.pivoted?(x=i.row[B]===t.id&&y.subRows,S=G.indexOf(t.id)>G.indexOf(i.row[B])&&y.subRows,P=x?u.default.normalizeComponent(E,a({},y,{value:r[H]}),r[H]):S?u.default.normalizeComponent(C,y,v):null):y.aggregated&&(P=u.default.normalizeComponent(C,y,v)),y.expander&&(P=u.default.normalizeComponent(k,y,r[H]),G&&(y.groupedByPivot&&(P=null),y.subRows||he||(P=null)));var R=w?function(t){var r=u.default.clone(re);return r=c?u.default.set(r,y.nestingPath,!1):u.default.set(r,y.nestingPath,{}),e.setStateWithData({expanded:r},(function(){ae&&ae(r,y.nestingPath,t)}))}:void 0,N={onClick:R};return g.rest.onClick&&(N.onClick=function(e){g.rest.onClick(e,R?function(){return R(e)}:void 0)}),h.rest.onClick&&(N.onClick=function(e){h.rest.onClick(e,R?function(){return R(e)}:void 0)}),l.default.createElement(fe,a({key:n+"-"+t.id,className:(0,s.default)(m,!f&&"hidden",y.expandable&&"rt-expandable",(x||S)&&"rt-pivot"),style:a({},b,{flex:d+" 0 auto",width:u.default.asPx(d),maxWidth:u.default.asPx(p)})},g.rest,h.rest,N),P)}))),i.subRows&&c&&i.subRows.map((function(e,r){return t(e,r,i.nestingPath)})),he&&!i.subRows&&c&&he(i))}(t,r)})),ze.map(Je)),_e?(n=k(He,void 0,void 0,e),c=u.default.splitProps(T(He,void 0,void 0,e)),l.default.createElement(de,a({className:n.className,style:a({},n.style,{minWidth:Ke+"px"})},n.rest),l.default.createElement(ue,a({className:(0,s.default)(c.className),style:c.style},c.rest),Oe.map(qe)))):null),D&&_?l.default.createElement("div",{className:"pagination-bottom"},j):null,!Ae.length&&l.default.createElement(me,et,u.default.normalizeComponent(I)),l.default.createElement(ge,a({loading:X,loadingText:M},Qe)))};return r?r(He,rt,this):rt()}}]),t}((0,f.default)((0,c.default)(i.Component)));h.propTypes=p.default,h.defaultProps=d.default,t.default=h},function(e,t){e.exports=window.reactR},function(e,t,r){var n; +/*! + Copyright (c) 2017 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}function s(e){return Array.isArray(e)}function u(e){return function e(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(s(t))for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=arguments[1],r=arguments[2],n=u(t),a=void 0,o=e;for(;(a=n.shift())&&n.length;)o[a]||(o[a]={}),o=o[a];return o[a]=r,e},takeRight:function(e,t){var r=t>e.length?0:e.length-t;return e.slice(r)},last:function(e){return e[e.length-1]},orderBy:function(e,t,r,n){return e.sort((function(e,a){for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e;return"function"==typeof e?Object.getPrototypeOf(e).isReactComponent?a.default.createElement(e,t):e(t):r},asPx:function(e){return e=Number(e),Number.isNaN(e)?null:e+"px"}}},function(e,t,r){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=function(e,t){var r=e[1]||"",n=e[3];if(!n)return r;if(t&&"function"==typeof btoa){var a=(i=n,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */"),o=n.sources.map((function(e){return"/*# sourceURL="+n.sourceRoot+e+" */"}));return[r].concat(o).concat([a]).join("\n")}var i;return[r].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+r+"}":r})).join("")},t.i=function(e,r){"string"==typeof e&&(e=[[null,e,""]]);for(var n={},a=0;a=0&&f.splice(t,1)}function b(e){var t=document.createElement("style");if(void 0===e.attrs.type&&(e.attrs.type="text/css"),void 0===e.attrs.nonce){var n=function(){0;return r.nc}();n&&(e.attrs.nonce=n)}return y(t,e.attrs),h(e,t),t}function y(e,t){Object.keys(t).forEach((function(r){e.setAttribute(r,t[r])}))}function v(e,t){var r,n,a,o;if(t.transform&&e.css){if(!(o="function"==typeof t.transform?t.transform(e.css):t.transform.default(e.css)))return function(){};e.css=o}if(t.singleton){var i=c++;r=u||(u=b(t)),n=S.bind(null,r,i,!1),a=S.bind(null,r,i,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(r=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",y(t,e.attrs),h(e,t),t}(t),n=C.bind(null,r,t),a=function(){m(r),r.href&&URL.revokeObjectURL(r.href)}):(r=b(t),n=P.bind(null,r),a=function(){m(r)});return n(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;n(e=t)}else a()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=i()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var r=g(e,t);return p(r,t),function(e){for(var n=[],a=0;a=a.pages?a.pages-1:a.page,0)),this.setState(a,(function(){t&&t(),n.page===a.page&&n.pageSize===a.pageSize&&n.sorted===a.sorted&&n.filtered===a.filtered||r.fireFetchData()}))}}]),t}(e)}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var r=[],n=!0,a=!1,o=void 0;try{for(var i,l=e[Symbol.iterator]();!(n=(i=l.next()).done)&&(r.push(i.value),!t||r.length!==t);n=!0);}catch(e){a=!0,o=e}finally{try{!n&&l.return&&l.return()}finally{if(a)throw o}}return r}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o=Object.assign||function(e){for(var t=1;t-1)&&s.default.getFirstDefined(e.show,!0)}));return o({},e,{columns:r})}return e}))).filter((function(e){return e.columns?e.columns.length:!(u.indexOf(e.id)>-1)&&s.default.getFirstDefined(e.show,!0)}))).findIndex((function(e){return e.pivot}));u.length&&function(){var e=[];u.forEach((function(t){var r=k.find((function(e){return e.id===t}));r&&e.push(r)}));var r=e.reduce((function(e,t){return e&&e===t.parentColumn&&t.parentColumn}),e[0].parentColumn),n=S&&r.Header,a={Header:n=n||function(){return l.default.createElement("strong",null,"Pivoted")},columns:e.map((function(e){return o({},t.props.pivotDefaults,e,{pivoted:!0})}))};E>=0?(a=o({},T[E],a),T.splice(E,1,a)):T.unshift(a)}();var R=[],N=[],A=function(e,r){R.push(o({},t.props.column,r,{columns:e})),N=[]};T.forEach((function(e,t){if(e.columns)return j=j.concat(e.columns),N.length>0&&A(N),void A(e.columns,e);j.push(e),N.push(e)})),S&&N.length>0&&A(N);var D=d.map((function(e,t){return function e(t,r){var n,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=(c(n={},y,t),c(n,v,r),c(n,h,t[h]),c(n,b,a),n);return k.forEach((function(e){e.expander||(o[e.id]=e.accessor(t))})),o[h]&&(o[h]=o[h].map((function(t,r){return e(t,r,a+1)}))),o}(e,t)})),z=function(e){var t={};return _.forEach((function(r){var n=e.map((function(e){return e[r.id]}));t[r.id]=r.aggregate(n,e)})),t},_=j.filter((function(e){return!e.expander&&e.aggregate}));return u.length&&(D=function e(t,r){var a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(a===r.length)return t;var i=Object.entries(s.default.groupBy(t,r[a])).map((function(e){var t,o=n(e,2),i=o[0],l=o[1];return c(t={},p,r[a]),c(t,g,i),c(t,r[a],i),c(t,h,l),c(t,b,a),c(t,w,!0),t}));return i=i.map((function(t){var n,i=e(t[h],r,a+1);return o({},t,(c(n={},h,i),c(n,m,!0),n),z(i))}))}(D,u)),o({},e,{resolvedData:D,allVisibleColumns:j,headerGroups:R,allDecoratedColumns:k,hasHeaderGroups:S})}},{key:"getSortedData",value:function(e){var t=e.manual,r=e.sorted,n=e.filtered,a=e.defaultFilterMethod,o=e.resolvedData,i=e.allVisibleColumns,l=e.allDecoratedColumns,s={};return l.filter((function(e){return e.sortMethod})).forEach((function(e){s[e.id]=e.sortMethod})),{sortedData:t?o:this.sortData(this.filterData(o,n,a,i),r,s)}}},{key:"fireFetchData",value:function(){this.props.onFetchData(this.getResolvedState(),this)}},{key:"getPropOrState",value:function(e){return s.default.getFirstDefined(this.props[e],this.state[e])}},{key:"getStateOrProp",value:function(e){return s.default.getFirstDefined(this.state[e],this.props[e])}},{key:"filterData",value:function(e,t,r,n){var a=this,i=e;return t.length&&(i=(i=t.reduce((function(e,t){var a=n.find((function(e){return e.id===t.id}));if(!a||!1===a.filterable)return e;var o=a.filterMethod||r;return a.filterAll?o(t,e,a):e.filter((function(e){return o(t,e,a)}))}),i)).map((function(e){return e[a.props.subRowsKey]?o({},e,c({},a.props.subRowsKey,a.filterData(e[a.props.subRowsKey],t,r,n))):e})).filter((function(e){return!e[a.props.subRowsKey]||e[a.props.subRowsKey].length>0}))),i}},{key:"sortData",value:function(e,t){var r=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t.length)return e;var a=(this.props.orderByMethod||s.default.orderBy)(e,t.map((function(e){return n[e.id]?function(t,r){return n[e.id](t[e.id],r[e.id],e.desc)}:function(t,n){return r.props.defaultSortMethod(t[e.id],n[e.id],e.desc)}})),t.map((function(e){return!e.desc})),this.props.indexKey);return a.forEach((function(e){e[r.props.subRowsKey]&&(e[r.props.subRowsKey]=r.sortData(e[r.props.subRowsKey],t,n))})),a}},{key:"getMinRows",value:function(){return s.default.getFirstDefined(this.props.minRows,this.getStateOrProp("pageSize"))}},{key:"onPageChange",value:function(e){var t=this.props,r=t.onPageChange,n=t.collapseOnPageChange,a={page:e};n&&(a.expanded={}),this.setStateWithData(a,(function(){r&&r(e)}))}},{key:"onPageSizeChange",value:function(e){var t=this.props.onPageSizeChange,r=this.getResolvedState(),n=r.pageSize*r.page,a=Math.floor(n/e);this.setStateWithData({pageSize:e,page:a},(function(){t&&t(e,a)}))}},{key:"sortColumn",value:function(e,t){var r=this.getResolvedState(),n=r.sorted,a=r.skipNextSort,o=r.defaultSortDesc,i=e.hasOwnProperty("defaultSortDesc")?e.defaultSortDesc:o,l=!i;if(a)this.setStateWithData({skipNextSort:!1});else{var u=this.props.onSortedChange,c=s.default.clone(n||[]).map((function(e){return e.desc=s.default.isSortingDesc(e),e}));if(s.default.isArray(e))!function(){var r=c.findIndex((function(t){return t.id===e[0].id}));r>-1?(c[r].desc===l?t?c.splice(r,e.length):e.forEach((function(e,t){c[r+t].desc=i})):e.forEach((function(e,t){c[r+t].desc=l})),t||(c=c.slice(r,e.length))):c=t?c.concat(e.map((function(e){return{id:e.id,desc:i}}))):e.map((function(e){return{id:e.id,desc:i}}))}();else{var f=c.findIndex((function(t){return t.id===e.id}));if(f>-1){var d=c[f];d.desc===l?t?c.splice(f,1):(d.desc=i,c=[d]):(d.desc=l,t||(c=[d]))}else t?c.push({id:e.id,desc:i}):c=[{id:e.id,desc:i}]}this.setStateWithData({page:!n.length&&c.length||!t?0:this.state.page,sorted:c},(function(){u&&u(c,e,t)}))}}},{key:"filterColumn",value:function(e,t){var r=this.getResolvedState().filtered,n=this.props.onFilteredChange,a=(r||[]).filter((function(t){if(t.id!==e.id)return!0}));""!==t&&a.push({id:e.id,value:t}),this.setStateWithData({filtered:a},(function(){n&&n(a,e,t)}))}},{key:"resizeColumnStart",value:function(e,t,r){var n=this;e.stopPropagation();var a=e.target.parentElement.getBoundingClientRect().width,o=void 0;o=r?e.changedTouches[0].pageX:e.pageX,this.trapEvents=!0,this.setStateWithData({currentlyResizing:{id:t.id,startX:o,parentWidth:a}},(function(){r?(document.addEventListener("touchmove",n.resizeColumnMoving),document.addEventListener("touchcancel",n.resizeColumnEnd),document.addEventListener("touchend",n.resizeColumnEnd)):(document.addEventListener("mousemove",n.resizeColumnMoving),document.addEventListener("mouseup",n.resizeColumnEnd),document.addEventListener("mouseleave",n.resizeColumnEnd))}))}},{key:"resizeColumnMoving",value:function(e){e.stopPropagation();var t=this.props.onResizedChange,r=this.getResolvedState(),n=r.resized,a=r.currentlyResizing,o=n.filter((function(e){return e.id!==a.id})),i=void 0;"touchmove"===e.type?i=e.changedTouches[0].pageX:"mousemove"===e.type&&(i=e.pageX);var l=Math.max(a.parentWidth+i-a.startX,11);o.push({id:a.id,value:l}),this.setStateWithData({resized:o},(function(){t&&t(o,e)}))}},{key:"resizeColumnEnd",value:function(e){e.stopPropagation();var t="touchend"===e.type||"touchcancel"===e.type;t&&(document.removeEventListener("touchmove",this.resizeColumnMoving),document.removeEventListener("touchcancel",this.resizeColumnEnd),document.removeEventListener("touchend",this.resizeColumnEnd)),document.removeEventListener("mousemove",this.resizeColumnMoving),document.removeEventListener("mouseup",this.resizeColumnEnd),document.removeEventListener("mouseleave",this.resizeColumnEnd),t||this.setStateWithData({skipNextSort:!0,currentlyResizing:!1})}}]),t}(e)}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}var c=function(){return{}};t.default={data:[],loading:!1,showPagination:!0,showPaginationTop:!1,showPaginationBottom:!0,showPageSizeOptions:!0,pageSizeOptions:[5,10,20,25,50,100],defaultPageSize:20,showPageJump:!0,collapseOnSortingChange:!0,collapseOnPageChange:!0,collapseOnDataChange:!0,freezeWhenExpanded:!1,sortable:!0,resizable:!0,filterable:!1,defaultSortDesc:!1,defaultSorted:[],defaultFiltered:[],defaultResized:[],defaultExpanded:{},defaultFilterMethod:function(e,t,r){var n=e.pivotId||e.id;return void 0===t[n]||String(t[n]).startsWith(e.value)},defaultSortMethod:function(e,t,r){return t=null==t?"":t,(e="string"==typeof(e=null==e?"":e)?e.toLowerCase():e)>(t="string"==typeof t?t.toLowerCase():t)?1:ediv{position:absolute;display:block;text-align:center;width:100%;top:50%;left:0;font-size:15px;color:rgba(0,0,0,.6);-webkit-transform:translateY(-52%);transform:translateY(-52%);-webkit-transition:all .3s cubic-bezier(.25,.46,.45,.94);transition:all .3s cubic-bezier(.25,.46,.45,.94)}.ReactTable .-loading.-active{opacity:1;z-index:2;pointer-events:all}.ReactTable .-loading.-active>div{-webkit-transform:translateY(50%);transform:translateY(50%)}.ReactTable .rt-resizing .rt-td,.ReactTable .rt-resizing .rt-th{-webkit-transition:none!important;transition:none!important;cursor:col-resize;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}",""])},function(e,t){e.exports=function(e){var t="undefined"!=typeof window&&window.location;if(!t)throw new Error("fixUrls requires window.location");if(!e||"string"!=typeof e)return e;var r=t.protocol+"//"+t.host,n=r+t.pathname.replace(/\/[^\/]*$/,"/");return e.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,(function(e,t){var a,o=t.trim().replace(/^"(.*)"$/,(function(e,t){return t})).replace(/^'(.*)'$/,(function(e,t){return t}));return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(o)?e:(a=0===o.indexOf("//")?o:0===o.indexOf("/")?r+o:n+o.replace(/^\.\//,""),"url("+JSON.stringify(a)+")")}))}},function(e,t,r){var n=r(19);"string"==typeof n&&(n=[[e.i,n,""]]);var a={hmr:!0,transform:void 0,insertInto:void 0};r(7)(n,a);n.locals&&(e.exports=n.locals)},function(e,t,r){(e.exports=r(6)(!1)).push([e.i,'.ReactTable{height:100%;background-color:#fff}.rt-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.rt-th{font-weight:600}.rt-td,.rt-th{padding:7px 8px;overflow-wrap:break-word;max-width:100%;word-wrap:break-word}.rt-compact .rt-td,.rt-compact .rt-th{padding:4px 6px}.rt-nowrap .rt-td,.rt-nowrap .rt-th{white-space:nowrap;text-overflow:ellipsis}.rt-th-content{overflow:hidden;text-overflow:ellipsis}.rt-td-select{-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.rt-select,.rt-td-select{display:-webkit-box;display:-ms-flexbox;display:flex}.rt-select{-webkit-box-align:center;-ms-flex-align:center;align-items:center}input[type=checkbox].rt-select-input,input[type=radio].rt-select-input{display:block;margin:0}.rt-align-left{text-align:left}.rt-align-right{text-align:right}.rt-align-center{text-align:center}.rt-table{border-width:1px;border-color:#e6e6e6}.rt-bordered .rt-table,.rt-outlined .rt-table{border-style:solid}.rt-th{border-bottom:2px solid #e6e6e6;border-left-width:1px;border-left-color:rgba(0,0,0,.05)}.rt-bordered .rt-th,.rt-outlined .rt-th{border-bottom-width:1px}.rt-td{border-top:1px solid #f2f2f2;border-left-width:1px;border-left-color:rgba(0,0,0,.05)}.rt-borderless .rt-td,.rt-tr-group:first-child>.rt-tr:first-child .rt-td{border-top:none}.rt-bordered .rt-td,.rt-bordered .rt-th{border-left-style:solid}.rt-bordered .rt-td:first-child,.rt-bordered .rt-th:first-child{border-left:none}.rt-th-group,.rt-th-group-none{border-bottom:none}.rt-th-group:after{content:"";position:absolute;margin:auto;left:8px;right:8px;bottom:0;width:100%;height:1px;background-color:#e6e6e6}.rt-bordered .rt-th-group:after,.rt-outlined .rt-th-group:after{left:0;right:0}.rt-tr-striped{background-color:rgba(0,0,0,.03)}.rt-tr-highlight:hover,.rt-tr-striped.rt-tr-highlight:hover{background-color:rgba(0,0,0,.05)}.rt-tr.-padRow{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ReactTable .rt-tbody{-ms-flex-negative:0;flex-shrink:0}@supports ((position:-webkit-sticky) or (position:sticky)){.ReactTable .rt-table{background:inherit}.ReactTable .rt-tbody{overflow:visible}.ReactTable .rt-thead.-header{top:0}.ReactTable .rt-tfoot,.ReactTable .rt-thead.-header{position:-webkit-sticky;position:sticky;background:inherit;z-index:2}.ReactTable .rt-tfoot{bottom:0}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){.ReactTable .rt-tbody{overflow:auto;-ms-overflow-style:-ms-autohiding-scrollbar}}.rt-td-filter{border-top:0;border-bottom:1px solid #f2f2f2}.rt-borderless .rt-td-filter{border-bottom:0}.rt-filter{padding:5px 7px;color:inherit;background-color:#fff;border:1px solid rgba(0,0,0,.1);border-radius:3px;font-family:inherit;font-size:inherit;font-weight:400;outline-width:0;outline-style:solid}.rt-filter:focus{border:1px solid rgba(0,0,0,.25)}.rt-sort-header{display:-webkit-box;display:-ms-flexbox;display:flex}.rt-align-center .rt-sort-header{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.rt-align-right .rt-sort-header{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.rt-th{outline-width:0;outline-style:solid}.rt-th[aria-sort] .rt-sort-left:after{padding-right:5px;line-height:0}.rt-th[aria-sort] .rt-sort-right:after{padding-left:5px;line-height:0}.rt-th[aria-sort=ascending] .rt-sort-left:after,.rt-th[aria-sort=ascending] .rt-sort-right:after{content:"\\2191"}.rt-th[aria-sort=descending] .rt-sort-left:after,.rt-th[aria-sort=descending] .rt-sort-right:after{content:"\\2193"}.rt-th[aria-sort=none] .rt-sort:after{content:"\\2195";opacity:.4}.rt-th[data-sort-hint=ascending] .rt-sort-left:after,.rt-th[data-sort-hint=ascending] .rt-sort-right:after{content:"\\2191";opacity:.4}.rt-th[data-sort-hint=descending] .rt-sort-left:after,.rt-th[data-sort-hint=descending] .rt-sort-right:after{content:"\\2193";opacity:.4}.rt-expander-button{margin:0 2px;padding:0;background:none;border:none;cursor:pointer}.rt-expander{display:inline-block;position:relative;padding:0 8px;color:transparent;outline-width:0;outline-style:solid}.rt-expander:after{content:"";position:absolute;width:0;height:0;top:50%;left:50%;-webkit-transform:translate(-50%,-50%) rotate(-90deg);transform:translate(-50%,-50%) rotate(-90deg);border-left:5.04px solid transparent;border-right:5.04px solid transparent;border-top:7px solid rgba(0,0,0,.8);-webkit-transition:all .3s cubic-bezier(.175,.885,.32,1.275);transition:all .3s cubic-bezier(.175,.885,.32,1.275);cursor:pointer}.rt-expander.-open:after{-webkit-transform:translate(-50%,-50%) rotate(0);transform:translate(-50%,-50%) rotate(0)}.rt-pagination{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:6px 4px;border-top:1px solid #f2f2f2}.rt-bordered .rt-pagination,.rt-outlined .rt-pagination{border-top:none}.rt-pagination-info :not(:last-child){margin-right:16px}.rt-page-info{display:inline-block;margin:6px 8px;opacity:.9}.rt-page-size{display:inline-block;margin:0 8px}.rt-page-size-select{margin:0 2px}.rt-page-button,.rt-page-jump,.rt-page-size-select{font-family:inherit;font-size:inherit;color:inherit;line-height:inherit}.rt-page-jump,.rt-page-size-select{background-color:#fff;padding:3px;border-radius:3px;border:1px solid rgba(0,0,0,.05)}@supports (-moz-appearance:none){.rt-page-size-select{-moz-appearance:none;padding-right:12px;background-image:url(\'data:image/svg+xml;charset=US-ASCII,\');background-repeat:no-repeat;background-position:right 6px center;background-size:6px}}.rt-page-button{padding:6px 12px;background-color:transparent;border:none;border-radius:3px;outline-width:0;outline-style:solid;cursor:pointer}.rt-page-button::-moz-focus-inner{padding:0;border-style:none}.rt-page-button:disabled{opacity:.6;cursor:default}.rt-page-button:hover{background-color:rgba(0,0,0,.04)}.rt-page-button:active{background-color:rgba(0,0,0,.08)}.rt-keyboard-active .rt-page-button:focus{background-color:rgba(0,0,0,.04)}.rt-page-button:disabled:focus,.rt-page-button:disabled:hover{background-color:transparent}.rt-page-button-current{font-weight:700}.rt-page-ellipsis{margin:0 4px;pointer-events:none}.rt-page-numbers{display:inline-block;margin:0 8px;white-space:nowrap}.rt-page-jump{width:70px;text-align:center}.rt-tbody-noData{position:relative}.rt-tbody-noData .rt-td{border-color:transparent}.rt-noData{display:block;position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);line-height:0;z-index:1}.rt-search{display:block;-ms-flex-item-align:end;align-self:flex-end;margin-bottom:8px;padding:5px 7px;color:inherit;background-color:#fff;border:1px solid rgba(0,0,0,.1);border-radius:3px;outline-width:0;outline-style:solid;font-family:inherit;font-size:inherit}.rt-search:active,.rt-search:focus{border:1px solid rgba(0,0,0,.25)}',""])},function(e,t,r){"use strict";r.r(t);var n=r(3),a=r(1),o=r.n(a),i=r(2),l=r.n(i),s=r(0),u=r.n(s);function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function f(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}var d=function(e){for(var t=1;tn&&(n=(t=t.trim()).charCodeAt(0)),n){case 38:return t.replace(h,"$1"+e.trim());case 58:return e.trim()+t.replace(h,"$1"+e.trim());default:if(0<1*r&&0s.charCodeAt(8))break;case 115:i=i.replace(s,"-webkit-"+s)+";"+i;break;case 207:case 102:i=i.replace(s,"-webkit-"+(102l.charCodeAt(0)&&(l=l.trim()),l=[l],0p)&&(L=(B=B.replace(" ",":")).length),0=4;++n,a-=4)t=1540483477*(65535&(t=255&e.charCodeAt(n)|(255&e.charCodeAt(++n))<<8|(255&e.charCodeAt(++n))<<16|(255&e.charCodeAt(++n))<<24))+(59797*(t>>>16)<<16),r=1540483477*(65535&(t^=t>>>24))+(59797*(t>>>16)<<16)^1540483477*(65535&r)+(59797*(r>>>16)<<16);switch(a){case 3:r^=(255&e.charCodeAt(n+2))<<16;case 2:r^=(255&e.charCodeAt(n+1))<<8;case 1:r=1540483477*(65535&(r^=255&e.charCodeAt(n)))+(59797*(r>>>16)<<16)}return(((r=1540483477*(65535&(r^=r>>>13))+(59797*(r>>>16)<<16))^r>>>15)>>>0).toString(36)},w={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};var x=/[A-Z]|^ms/g,S=/_EMO_([^_]+?)_([^]*?)_EMO_/g,P=function(e){return 45===e.charCodeAt(1)},C=function(e){return null!=e&&"boolean"!=typeof e},O=function(e){var t={};return function(r){return void 0===t[r]&&(t[r]=e(r)),t[r]}}((function(e){return P(e)?e:e.replace(x,"-$&").toLowerCase()})),k=function(e,t){switch(e){case"animation":case"animationName":if("string"==typeof t)return t.replace(S,(function(e,t,r){return j={name:t,styles:r,next:j},t}))}return 1===w[e]||P(e)||"number"!=typeof t||0===t?t:t+"px"};function T(e,t,r,n){if(null==r)return"";if(void 0!==r.__emotion_styles)return r;switch(typeof r){case"boolean":return"";case"object":if(1===r.anim)return j={name:r.name,styles:r.styles,next:j},r.name;if(void 0!==r.styles){var a=r.next;if(void 0!==a)for(;void 0!==a;)j={name:a.name,styles:a.styles,next:j},a=a.next;return r.styles+";"}return function(e,t,r){var n="";if(Array.isArray(r))for(var a=0;ae.length)&&(t=e.length);for(var r=0,n=new Array(t);r'+'\')')}}),".rt-page-button":B({},q),".rt-page-button:not(:disabled):hover":B({},X),".rt-page-button:not(:disabled):active":B({},Y),".rt-keyboard-active & .rt-page-button:not(:disabled):focus":B({},X),".rt-page-button-current":B({},Z)})};return function e(t){for(var r=0,n=Object.entries(t);r1&&void 0!==arguments[1]?arguments[1]:{};if(!e||!t)return e;var r=Object.keys(t),n="("+r.map((function(e){return"{".concat(e,"}")})).join("|")+")",a=e.split(new RegExp(n)),o=r.reduce((function(e,r){return e["{".concat(r,"}")]=t[r],e}),{}),i=a.map((function(e){return null!=o[e]?o[e]:e}));return i.some((function(e){return"object"===J(e)}))?i:i.join("")}function X(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function Y(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}var he=function(e){var t=e.isCurrent,r=e.className,n=ge(e,["isCurrent","className"]);return r=Q(r,"rt-page-button",t?" rt-page-button-current":null),o.a.createElement("button",pe({type:"button",className:r},n),n.children)};var me=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&ie(e,t)}(l,e);var t,r,n,a,i=(t=l,function(){var e,r=ce(t);if(ue()){var n=ce(this).constructor;e=Reflect.construct(r,arguments,n)}else e=r.apply(this,arguments);return le(this,e)});function l(e){var t;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,l),(t=i.call(this,e)).changePage=t.changePage.bind(se(t)),t.applyPage=t.applyPage.bind(se(t)),t.state={pageJumpValue:e.page+1,prevPage:e.page},t}return r=l,a=[{key:"getDerivedStateFromProps",value:function(e,t){return e.page!==t.prevPage?{pageJumpValue:e.page+1,prevPage:e.page}:null}}],(n=[{key:"changePage",value:function(e){e!==this.props.page+1&&this.props.onPageChange(e-1)}},{key:"applyPage",value:function(e){e&&e.preventDefault();var t=this.state.pageJumpValue;if(""!==t)this.changePage(t);else{var r=this.props.page+1;this.setState({pageJumpValue:r})}}},{key:"renderPageInfo",value:function(e){var t=e.page,r=e.pageSize,n=e.sortedData,a=e.language,i=n.length,l=Math.min(t*r+1,n.length),s=Math.min(t*r+r,n.length),u=q(a.pageInfo,{rowStart:l,rowEnd:s,rows:i});return o.a.createElement("div",{className:"rt-page-info"},u)}},{key:"renderPageSizeOptions",value:function(e){var t=e.pageSize,r=e.pageSizeOptions,n=e.onPageSizeChange,a=e.language,i=o.a.createElement("select",{key:"page-size-select",className:"rt-page-size-select","aria-label":a.pageSizeOptionsLabel,onChange:function(e){return n(Number(e.target.value))},value:t},r.map((function(e,t){return o.a.createElement("option",{key:t,value:e},e)}))),l=q(a.pageSizeOptions,{rows:i});return o.a.createElement("div",{className:"rt-page-size"},l)}},{key:"renderPageJump",value:function(e){var t=e.onChange,r=e.value,n=e.onBlur,a=e.onKeyPress,i=e.inputType,l=e.language;return o.a.createElement("input",{key:"page-jump",className:"rt-page-jump","aria-label":l.pageJumpLabel,type:i,onChange:t,value:r,onBlur:n,onKeyPress:a})}},{key:"getPageJumpProperties",value:function(){var e=this;return{onKeyPress:function(t){13!==t.which&&13!==t.keyCode||e.applyPage()},onBlur:this.applyPage,value:this.state.pageJumpValue,onChange:function(t){var r=t.target.value;if(""!==r){var n=Number(r);if(!Number.isNaN(n)){var a=Math.min(Math.max(n,1),Math.max(e.props.pages,1));e.setState({pageJumpValue:a})}}else e.setState({pageJumpValue:r})},inputType:"number",language:this.props.language}}},{key:"render",value:function(){var e=this,t=this.props,r=t.autoHidePagination,n=t.paginationType,a=t.showPageSizeOptions,i=t.showPageInfo,l=t.page,s=t.pages,u=t.canPrevious,c=t.canNext,f=t.className,d=t.style,p=t.theme,g=t.language;if(r){var h=this.props,m=h.defaultPageSize,b=h.pageSizeOptions,y=h.resolvedData,v=a?Math.min.apply(Math,[m].concat(fe(b))):m;if(y.length<=v)return null}var w,x=i?this.renderPageInfo(this.props):null,S=a?this.renderPageSizeOptions(this.props):null,P=l+1,C=function(e,t){return t<=6?fe(Array(t)).map((function(e,t){return t+1})):e<=4?[1,2,3,4,5,t]:t-e<3?[1,t-3,t-2,t-1,t]:[1,e-1,e,e+1,t]}(P,s);if("numbers"===n){var O=[];C.forEach((function(t,r){var n=P===t,a=o.a.createElement(he,{key:t,isCurrent:n,onClick:e.changePage.bind(null,t),"aria-label":q(g.pageNumberLabel,{page:t})+(n?" ":""),"aria-current":n?"page":null},t);t-C[r-1]>1&&O.push(o.a.createElement("span",{className:"rt-page-ellipsis",key:"ellipsis-".concat(t),role:"separator"},"...")),O.push(a)})),w=O}else{var k="jump"===n?this.renderPageJump(this.getPageJumpProperties()):P,T=Math.max(s,1);w=o.a.createElement("div",{className:"rt-page-numbers"},q(g.pageNumbers,{page:k,pages:T}))}var j=o.a.createElement(he,{className:"rt-prev-button",onClick:function(){u&&e.changePage(P-1)},disabled:!u,"aria-disabled":u?null:"true","aria-label":g.pagePreviousLabel},g.pagePrevious),E=o.a.createElement(he,{className:"rt-next-button",onClick:function(){c&&e.changePage(P+1)},disabled:!c,"aria-disabled":c?null:"true","aria-label":g.pageNextLabel},g.pageNext);return o.a.createElement("div",{className:Q(f,"rt-pagination",V(p.paginationStyle)),style:d},o.a.createElement("div",{className:"rt-pagination-info"},x,S),o.a.createElement("div",{className:"rt-pagination-nav"},j,w,E))}}])&&oe(r.prototype,n),a&&oe(r,a),l}(o.a.Component);function be(e){return(be="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ye(){return(ye=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}function Ce(e,t){for(var r=0;re.length)&&(t=e.length);for(var r=0,n=new Array(t);r1?" (".concat(t[e],")"):"")})).join(", ")}};function He(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3;if(!Number.isFinite(e))return e;t=t>0?t:0;var r=Math.pow(10,t);return Math.sign(e)*Math.round(Math.abs(e)*r)/r}function Ge(e){return e.map(Ue).filter((function(e){return"number"==typeof e}))}function Ue(e){return(null==e||void 0===e||Ve(e))&&(e=null),"Inf"===e&&(e=1/0),"-Inf"===e&&(e=-1/0),"string"==typeof e&&(e=Number(e)),e}function Ve(e){return"NA"===e||"NaN"===e}function Je(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function $e(e){for(var t=1;t=e.length?{done:!0}:{done:!1,value:e[t++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,a,o=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return o=e.done,e},e:function(e){i=!0,a=e},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw a}}}}function Ye(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r0&&void 0!==arguments[0]?arguments[0]:{},t=e.type,r=e.naLast;return function(e,n,a){return"numeric"===t?(e=Ue(e),n=Ue(n)):(e="string"==typeof e?e.toLowerCase():e,n="string"==typeof n?n.toLowerCase():n),e===n?0:null==e?r?a?-1:1:-1:null==n?r?a?1:-1:1:e>n?1:ee.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(a[r]=e[r]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(a[r]=e[r])}return a}function st(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ut(e,t){for(var r=0;r1&&t.preventDefault(),e.setState({clicked:!0})},onFocus:function(){e.state.clicked||o||i||e.setState({showFocus:!0})},onBlur:function(){e.setState({showFocus:!1,clicked:!1})},tabIndex:"0","data-sort-hint":this.state.showFocus?n:void 0})}return Ft(l)}}]),r}(o.a.Component);Object.assign(i.ReactTableDefaults,{ThComponent:Mt});var It=function(e){return{state:e}},Lt=i.ReactTableDefaults.TbodyComponent,Wt=i.ReactTableDefaults.NoDataComponent;Object.assign(i.ReactTableDefaults,{TbodyComponent:function(e){var t=e.state,r=e.className,n=e.children,a=lt(e,["state","className","children"]),i=t.pageRows,l=t.theme,s=t.language,u=!i.length&&o.a.createElement(Wt,null,s.noData);return r=u?Q(r,"rt-tbody-noData"):r,r=Q(r,V(l.tableBodyStyle)),o.a.createElement(Lt,yt({role:"rowgroup",className:r},a),n,u)},NoDataComponent:function(){return null}}),Object.assign(i.ReactTableDefaults,{FilterComponent:function(e){var t=e.column,r=e.filter,n=e.onChange,a=t.name,i=t.theme,l=t.language;return o.a.createElement("input",{type:"text",className:Q("rt-filter",V(i.filterInputStyle)),style:{width:"100%"},value:r?r.value:"",onChange:function(e){return n(e.target.value)},placeholder:l.filterPlaceholder,"aria-label":q(l.filterLabel,{name:a})})}}),Object.assign(i.ReactTableDefaults,{ExpanderComponent:function(e){var t=e.isExpanded,r=e.column,n=r.theme,a=r.language,i=t?a.detailsCollapseLabel:a.detailsExpandLabel;return o.a.createElement("button",{className:"rt-expander-button","aria-label":i},o.a.createElement("span",{className:Q("rt-expander",t&&"-open",V(n.expanderStyle)),tabIndex:"-1","aria-hidden":"true"},"•"))}});var Kt=i.ReactTableDefaults.LoadingComponent;Object.assign(i.ReactTableDefaults,{LoadingComponent:function(e){var t=e.loading,r=lt(e,["loading"]);return t?Kt(wt({loading:t},r)):null}}),l.a.propTypes=d,l.a.prototype.oldComponentWillReceiveProps=l.a.prototype.UNSAFE_componentWillReceiveProps,l.a.prototype.UNSAFE_componentWillReceiveProps=function(e,t){var r=this;e=wt({},e),this.props.dataKey&&this.props.dataKey===e.dataKey&&(e.data=this.props.data,e.columns=this.props.columns);return["pivotBy","sorted","filtered"].forEach((function(t){JSON.stringify(r.props[t])===JSON.stringify(e[t])&&(e[t]=r.props[t])})),this.props.searchable!==e.searchable&&(e.filtered=this.state.filtered.filter((function(e){return e.id!==r.props.searchKey}))),this.oldComponentWillReceiveProps(e,t)},l.a.prototype.oldFilterData=l.a.prototype.filterData,l.a.prototype.filterData=function(e,t,r,n){var a=n;if(this.props.searchable){var o=n.filter((function(e){return e.createMatcher})),i={id:this.props.searchKey,filterAll:!0,filterable:!0,filterMethod:function(e,t){if(!e.value)return t;var r=o.reduce((function(t,r){return t[r.id]=r.createMatcher(e.value),t}),{});return t=t.filter((function(e){if(e._subRows)return!0;var t,n=function(e){if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(e=at(e))){var t=0,r=function(){};return{s:r,n:function(){return t>=e.length?{done:!0}:{done:!1,value:e[t++]}},e:function(e){throw e},f:r}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var n,a,o=!0,i=!1;return{s:function(){n=e[Symbol.iterator]()},n:function(){var e=n.next();return o=e.done,e},e:function(e){i=!0,a=e},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw a}}}}(o);try{for(n.s();!(t=n.n()).done;){var a=t.value,i=e._original[a.id];if(r[a.id](i))return!0}}catch(e){n.e(e)}finally{n.f()}}))}};a=a.concat(i)}if(this.props.crosstalkGroup){var l={id:this.props.crosstalkId,filterAll:!0,filterable:!0,filterMethod:function(e,t){return e.value?t=t.filter((function(t){return!!t._subRows||(!!e.value.includes(t._index)||void 0)})):t}};a=a.concat(l)}return this.oldFilterData(e,t,r,a)};var Bt,Ht,Gt,Ut=function(e){var t=e.searchValue,r=e.onSearchChange,n=e.searchPlaceholder,l=e.searchLabel,s=e.searchClassName,u=lt(e,["searchValue","onSearchChange","searchPlaceholder","searchLabel","searchClassName"]),c=o.a.createElement("input",{type:"text",value:t,onChange:r,className:Q("rt-search",s),placeholder:n,"aria-label":l});return o.a.createElement(a.Fragment,null,c,o.a.createElement(i.ReactTableDefaults.TableComponent,u))},Vt=(Bt=l.a,(Gt=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Oe(e,t)}(l,e);var t,r,n,a,i=(t=l,function(){var e,r=je(t);if(Te()){var n=je(this).constructor;e=Reflect.construct(r,arguments,n)}else e=r.apply(this,arguments);return ke(this,e)});function l(e){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,l),i.call(this,e)}return r=l,(n=[{key:"rowSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.toggleSelection,a=t.selectType,i=t.SelectInputComponent,l=t.language,s=r(e.index),u={checked:s,onClick:n,selectType:a,row:e.row,label:s?l.deselectRowLabel:l.selectRowLabel};return o.a.createElement(i,u)}},{key:"subRowSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.toggleAll,a=t.selectType,i=t.SelectInputComponent,l=t.language;if("radio"===a)return null;var s=e.subRows;if(!s||s.some((function(e){return e._aggregated})))return null;var u=s.every((function(e){return r(e._index)})),c={checked:u,onClick:n,selectType:a,rows:s,label:u?l.deselectAllSubRowsLabel:l.selectAllSubRowsLabel};return o.a.createElement(i,c)}},{key:"headSelector",value:function(e){var t=this.props,r=t.isSelected,n=t.selectType,a=t.toggleAll,i=t.SelectAllInputComponent,l=t.language;if("radio"===n)return null;var s=e.data;if(0===s.length||s.some((function(e){return e._aggregated})))return null;var u=s.every((function(e){return r(e._index)})),c={checked:u,onClick:a,selectType:n,rows:s,label:u?l.deselectAllRowsLabel:l.selectAllRowsLabel};return o.a.createElement(i,c)}},{key:"render",value:function(){for(var e=this,t=this.props,r=t.columns,n=t.selectWidth,a=t.forwardedRef,i=Pe(t,["columns","selectWidth","forwardedRef"]),l=this.props,s=l.isSelected,u=l.selectType,c=l.toggleAll,f=l.toggleSelection,d=l.selectId,p={},g=0;g1&&void 0!==arguments[1])||arguments[1];this.setState({selected:new Set(e)},(function(){return t.onSelectedChange(r)}))}},{key:"onSelectedChange",value:function(){var e=this,t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],r=this.props,n=r.selection,a=r.selectionId;if(n&&a&&window.Shiny){var o=nt(this.state.selected).map((function(e){return e+1}));window.Shiny.onInputChange(a,o)}if(this.ctSelection&&t){var i=nt(this.state.selected).map((function(t){return e.props.crosstalkKey[t]}));this.ctSelection.set(i)}}},{key:"toggleExpand",value:function(e,t){var r=wt({},this.state.expanded);if(t){var n=te(r,e.nestingPath);r=n&&n===t.id?re(r,e.nestingPath,void 0):re(r,e.nestingPath,t.id)}else{var a=te(r,e.nestingPath);r=re(r,e.nestingPath,a?void 0:{})}this.setState({expanded:r})}},{key:"isExpanded",value:function(e){var t=te(this.state.expanded,e.nestingPath);return t&&t===e.column.id}},{key:"toggleExpandAll",value:function(){var e=this.tableInstance.current.state,t=e.columns,r=e.sortedData,n=t.find((function(e){return e.details})),a=function e(t){return t.reduce((function(t,r,a){return r._subRows?t[a]=e(r._subRows):t[a]=n?n.id:{},t}),{})}(r);this.setState({expanded:a})}},{key:"toggleCollapseAll",value:function(){this.setState({expanded:{}})}},{key:"getRowInfo",value:function(e){var t=this;return e&&this.props.selection?wt({selected:e.subRows&&"multiple"===this.props.selection?e.subRows.every((function(e){return t.isSelected(e._index)})):this.isSelected(e.index)},e):e}},{key:"onTableUpdate",value:function(){if(window.Shiny&&window.Shiny.onInputChange&&!this.props.nested){var e=this.tableElement.current,t=this.tableInstance.current;if(!e||!t)return;var r=e.parentElement.getAttribute("data-reactable-output");if(!r)return;var n={page:t.state.page+1,pageSize:t.state.pageSize,pages:t.state.pages,selected:nt(this.state.selected).map((function(e){return e+1}))};Object.keys(n).forEach((function(e){window.Shiny.onInputChange("".concat(r,"__reactable__").concat(e),n[e])}))}}},{key:"componentDidMount",value:function(){var e=this;if(this.state.selected.size>0&&this.onSelectedChange(),!0===this.state.expanded&&this.toggleExpandAll(),window.Shiny&&!this.props.nested){var t=this.tableElement.current.parentElement.getAttribute("data-reactable-output");if(t){window.Shiny.addCustomMessageHandler("__reactable__".concat(t),(function(t){null!=t.selected&&e.setSelection(t.selected),null!=t.expanded&&(t.expanded?e.toggleExpandAll():e.toggleCollapseAll()),null!=t.page&&e.tableInstance.current.onPageChange(t.page)}))}}this.onTableUpdate();var r=this.props,n=r.crosstalkKey,a=r.crosstalkGroup;if(a&&window.crosstalk){this.ctSelection=new window.crosstalk.SelectionHandle(a),this.ctFilter=new window.crosstalk.FilterHandle(a),this.ctSelected=null,this.ctFiltered=null;var o=n.reduce((function(e,t,r){return e[t]=r,e}),{}),i=this.tableInstance.current,l={id:i.props.crosstalkId},s=function(){var t,r=e.ctSelected&&e.ctSelected.length>0?e.ctSelected:null,n=e.ctFiltered,a=(t=r||n?r?n?r.filter((function(e){return n.includes(e)})):r:n:null)?t.map((function(e){return o[e]})):null;i.filterColumn(l,a)},u=function(t){e.ctSelected!==t&&(e.ctSelected=t,s())};this.ctSelection.on("change",(function(t){t.sender!==e.ctSelection?(u(t.value),e.setSelection([],!1)):u(null)})),this.ctFilter.on("change",(function(t){var r;t.sender!==e.ctFilter&&(r=t.value,e.ctFiltered!==r&&(e.ctFiltered=r,s()))}))}}},{key:"componentDidUpdate",value:function(e){var t=this.props,r=t.defaultSelected,n=t.defaultExpanded;if(e.defaultSelected!==r){var a=new Set(r);this.setState({selected:a},this.onSelectedChange)}if(e.defaultExpanded!==n)if(!0===n)this.toggleExpandAll();else{var o=n||{};this.setState({expanded:o})}}},{key:"componentWillUnmount",value:function(){this.ctSelection&&this.ctSelection.close(),this.ctFilter&&this.ctFilter.close()}},{key:"render",value:function(){var e=this,t=this.props,s=t.data,u=t.columns,c=t.columnGroups,f=t.pivotBy,d=t.sortable,p=t.resizable,g=t.filterable,h=t.searchable,m=t.defaultSortDesc,b=t.defaultSorted,y=t.defaultPageSize,v=t.pageSizeOptions,w=t.paginationType,x=t.showPagination,S=t.showPageSizeOptions,P=t.showPageInfo,C=t.minRows,O=t.selection,k=t.onClick,T=t.outlined,j=t.bordered,E=t.borderless,R=t.striped,N=t.highlight,A=t.compact,D=t.nowrap,z=t.showSortIcon,_=t.showSortable,F=t.className,M=t.style,I=t.rowClassName,L=t.rowStyle,W=t.inline,K=t.width,B=t.height,H=t.language,U=t.crosstalkGroup,J=t.crosstalkKey,q=t.dataKey,X=t.theme;for(var Y in F=Q(F,V((X=G(X)||{}).style)),H=wt({},$,{},H))H[Y]=H[Y]||null;s=function(e){for(var t=Object.keys(e),r=new Array(e[t[0]].length),n=0;n2&&void 0!==arguments[2]?arguments[2]:{},l=r.sortable,s=r.showSortIcon,u=r.showSortable,c=r.isExpanded,f=r.onExpanderClick,d=r.theme,p=r.language;return e=e.map((function(e){var t=$e({},e);if(t.id=t.accessor,t.accessor.includes(".")&&(t.accessor=function(e){return e[t.id]}),"string"==typeof t.aggregate&&Be[t.aggregate]){var r=t.aggregate;t.aggregate=Be[r]}t.sortMethod=Qe({type:t.type,naLast:t.sortNALast}),t.filterAll=!0,"numeric"===t.type?t.createMatcher=tt:t.createMatcher=rt,t.filterMethod=function(e,r){var n=e.id,a=t.createMatcher(e.value);return r.filter((function(e){var t=e[n];return void 0===t||(!!e._subRows||a(t))}))},"numeric"===t.type?t.align=t.align||"right":t.align=t.align||"left",t.Cell=function(e){var r,l,s=e.value,u=null==s||"numeric"===t.type&&Ve(s);return u&&(s=t.na),!u&&t.format&&t.format.cell&&(s=et(s,t.format.cell)),t.cell&&("function"==typeof t.cell&&(s=t.cell($e({},e,{value:s}))),t.cell instanceof Array&&!e.aggregated&&(s=t.cell[e.index])&&(s=Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.cell[e.index]))),null!=s&&""!==s||(s="​"),r=o.a.isValidElement(s)?s:t.html?o.a.createElement("div",{style:{display:"inline"},dangerouslySetInnerHTML:{__html:s}}):String(s),t.details&&(t.details instanceof Array&&null==t.details[e.index]||(l=i.ReactTableDefaults.ExpanderComponent($e({},e,{isExpanded:c(e)})))),l?o.a.createElement(o.a.Fragment,null,l,r):r},t.PivotValue=function(e){var r=t.Cell(e);return o.a.createElement("span",null,r," ",e.subRows&&"(".concat(e.subRows.length,")"))},t.Aggregated=function(e){var r=null!=e.value?e.value:"";return t.format&&t.format.aggregated&&(r=et(r,t.format.aggregated)),t.aggregated&&(r=t.aggregated($e({},e,{value:r}))),t.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):r},t.Header=function(e){var r,i=t.name;if(t.header&&(i="function"==typeof t.header?t.header(e):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.header)),r=o.a.isValidElement(i)?o.a.createElement("div",{className:"rt-th-content"},i):t.html?o.a.createElement("div",{className:"rt-th-content",dangerouslySetInnerHTML:{__html:i}}):o.a.createElement("span",{className:"rt-th-content"},null!=i?String(i):""),ee(t.sortable,l)&&s){var c=u?"rt-sort":"";return"right"===t.align?o.a.createElement("div",{className:"rt-sort-header"},o.a.createElement("span",{className:Q(c,"rt-sort-left"),"aria-hidden":"true"}),r):o.a.createElement("div",{className:"rt-sort-header"},r,o.a.createElement("span",{className:Q(c,"rt-sort-right"),"aria-hidden":"true"}))}return r},t.footer&&(t.Footer=function(e){var r;return r="function"==typeof t.footer?t.footer(e):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},t.footer),o.a.isValidElement(r)?r:t.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):null!=r?String(r):""});var g="rt-align-".concat(t.align);t.headerClassName=Q(g,t.headerClassName),t.footerClassName=Q(g,t.footerClassName);var h=t.className,m=t.style;return t.className=void 0,t.style=void 0,t.getProps=function(e,t,r){var n,a,o={};if(!t)return o;(n="function"==typeof h?h(t,r,e):h instanceof Array?h[t.index]:h,o.className=Q(g,n),m)&&((a="function"==typeof m?m(t,r,e):m instanceof Array?m[t.index]:m)&&(o.style=a));return r.details&&(r.details instanceof Array&&null==r.details[t.index]||t.aggregated||(o.className=Q("rt-expandable",o.className),null==t.row[r.id]&&(o.style=$e({},o.style,{textOverflow:"inherit"})),o.onClick=function(e,n){f(t,r),n&&n()})),o},t.theme=d,t.language=p,t})),t&&(e=Ze(e,t)).forEach((function(e){(null!=e.name||e.header)&&(e.Header=function(t){var r=e.name;return e.header&&(r="function"==typeof e.header?e.header(t):Object(n.hydrate)({Fragment:a.Fragment,WidgetContainer:Me},e.header)),o.a.isValidElement(r)?r:e.html?o.a.createElement("div",{dangerouslySetInnerHTML:{__html:r}}):null!=r?String(r):""}),e.align=e.align||"center",e.headerClassName=Q("rt-align-".concat(e.align),e.headerClassName)})),e}(u,c,{sortable:d,showSortIcon:z,showSortable:_,isExpanded:this.isExpanded,onExpanderClick:this.toggleExpand,theme:X,language:H}),null!=C&&(C=Math.max(C,1)),F=Q(F,T?"rt-outlined":"",j?"rt-bordered":"",E?"rt-borderless":"",A?"rt-compact":"",W?" rt-inline":"",D?"rt-nowrap":""),M=wt({width:K,height:B},M);var Z=l.a,re={};O&&(Z=Vt,re={isSelected:this.isSelected,toggleSelection:this.toggleSelection,toggleAll:this.toggleSelectionAll,selectType:"multiple"===O?"checkbox":"radio"});var ne=null==x,ae=Rt;(R||N||O||I||L)&&(ae=function(t,r){r=e.getRowInfo(r);var n,a=Rt(t,r);(R&&r&&(a.className=Q(a.className,r.viewIndex%2?null:"rt-tr-striped")),N&&r&&(a.className=Q(a.className,"rt-tr-highlight")),r&&r.selected&&(a.className=Q(a.className,"rt-tr-selected")),I)&&(n="function"==typeof I?I(r,t):I instanceof Array?r&&I[r.index]:I,a.className=Q(a.className,n));return L&&(a.style="function"==typeof L?L(r,t):L instanceof Array?r&&L[r.index]:L),a});var oe,ie=u.reduce((function(e,t){return e.concat(t.columns?t.columns:t)}),[]);ie.some((function(e){return e.details}))?(oe=function(t){var i=te(e.state.expanded,t.nestingPath),l=ie.find((function(e){return e.id===i})),s=l.details,u=l.html,c={};if("function"==typeof s){var f=s(e.getRowInfo(t));u&&(c.html=f),c.children=f}else if(s instanceof Array){var d=s[t.index];if(null==d)return null;u&&(c.html=d),c.children=Object(n.hydrate)({Reactable:r,Fragment:a.Fragment,WidgetContainer:Me},d)}return o.a.createElement(Jt,yt({key:i},c))},u=[{expander:!0,show:!1}].concat(nt(u))):oe=null;var le,se=function(){Object.keys(e.state.expanded).length>0&&e.setState({expanded:{}})},ue=Nt;k&&("select"===k?k=function(t,r){if(t&&(!r.pivoted||!t.aggregated))if(t.aggregated){if("single"===O)return;var n=t.subRows;if(!n||n.some((function(e){return e._aggregated})))return null;var a=n.map((function(e){return e._index})),o=a.every((function(t){return e.isSelected(t)}));e.toggleSelectionAll(a,!o)}else e.toggleSelection(t.index)}:"expand"===k&&(k=function(t,r){if(t){var n=ie.find((function(e){return e.details}));if(t.aggregated)r.pivoted||e.toggleExpand(t);else if(n){var a=n.details;if(a instanceof Array&&null==a[t.index])return;e.toggleExpand(t,n)}}}),ue=function(e,t,r){return wt({},Nt(e,t),{onClick:function(n,a){k(t,r,e),a&&a()}})});var ce=St;return h&&(le=Ut,ce=function(e,t,r,n){var a=e.filtered.find((function(t){return t.id===e.searchKey})),o=a?a.value:"";return wt({},St(e),{searchValue:o,onSearchChange:function(t){n.filterColumn({id:e.searchKey},t.target.value)},searchPlaceholder:e.language.searchPlaceholder,searchLabel:e.language.searchLabel,searchClassName:V(e.theme.searchInputStyle)})}),o.a.createElement(Z,yt({data:s,columns:u,pivotBy:f||[],sortable:d,resizable:p,filterable:g,searchable:h,searchKey:"__search__",defaultSortDesc:m,defaultSorted:b,defaultPageSize:y,pageSizeOptions:v,showPagination:x,showPageSizeOptions:S,PaginationComponent:me,paginationType:w,autoHidePagination:ne,showPageInfo:P,minRows:C,collapseOnSortingChange:!0,collapseOnPageChange:!0,collapseOnDataChange:!1,className:F,style:M,expanded:this.state.expanded,onExpandedChange:function(t){e.setState({expanded:t})},onPageChange:se,onSortedChange:se,getTableProps:ce,getTheadGroupTrProps:Ot,getTheadGroupThProps:Ct,getTheadTrProps:kt,getTheadThProps:Pt,getTheadFilterTrProps:Tt,getTheadFilterThProps:jt,getTbodyProps:It,getTrGroupProps:Et,getTrProps:ae,getTdProps:ue,getTfootTrProps:At,getTfootTdProps:Dt,TableComponent:le,SubComponent:oe},re,{theme:X,language:H,crosstalkGroup:U,crosstalkKey:J,crosstalkId:"__crosstalk__",key:"".concat(y),dataKey:q,ref:this.tableInstance,getProps:function(){return e.onTableUpdate(),{ref:e.tableElement,onMouseDown:function(){e.tableElement.current.classList.remove("rt-keyboard-active")},onKeyDown:function(){e.tableElement.current.classList.add("rt-keyboard-active")},onKeyUp:function(t){9===(t.which||t.keyCode)&&e.tableElement.current.classList.add("rt-keyboard-active")}}}}))}}]),r}(o.a.Component);$t.defaultProps={sortable:!0,resizable:!1,showPageSizeOptions:!1,showSortIcon:!0};var qt=$t;Object(n.reactWidget)("reactable","output",{Reactable:qt})}]); +//# sourceMappingURL=reactable.js.map \ No newline at end of file diff --git a/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/twitter-widget-0.0.1/widgets.js b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/twitter-widget-0.0.1/widgets.js new file mode 100644 index 00000000..b30be8c6 --- /dev/null +++ b/docs/posts/2020-09-12-videos-in-reactable/2020-09-12-videos-in-reactable_files/twitter-widget-0.0.1/widgets.js @@ -0,0 +1,8 @@ +Function&&Function.prototype&&Function.prototype.bind&&(/(MSIE ([6789]|10|11))|Trident/.test(navigator.userAgent)||(window.__twttr&&window.__twttr.widgets&&window.__twttr.widgets.loaded&&window.twttr.widgets.load&&window.twttr.widgets.load(),window.__twttr&&window.__twttr.widgets&&window.__twttr.widgets.init||function(t){function e(e){for(var n,i,o=e[0],s=e[1],a=0,c=[];a-1},forIn:i,isObject:s,isEmptyObject:a,toType:o,isType:function(t,e){return t==o(e)},toRealArray:u}},function(t,e){t.exports=window},function(t,e,n){var r=n(6);t.exports=function(){var t=this;this.promise=new r(function(e,n){t.resolve=e,t.reject=n})}},function(t,e,n){var r=n(11),i=/(?:^|(?:https?:)?\/\/(?:www\.)?twitter\.com(?::\d+)?(?:\/intent\/(?:follow|user)\/?\?screen_name=|(?:\/#!)?\/))@?([\w]+)(?:\?|&|$)/i,o=/(?:^|(?:https?:)?\/\/(?:www\.)?twitter\.com(?::\d+)?\/(?:#!\/)?[\w_]+\/status(?:es)?\/)(\d+)/i,s=/^http(s?):\/\/(\w+\.)*twitter\.com([:/]|$)/i,a=/^http(s?):\/\/(ton|pbs)\.twimg\.com/,u=/^#?([^.,<>!\s/#\-()'"]+)$/,c=/twitter\.com(?::\d{2,4})?\/intent\/(\w+)/,d=/^https?:\/\/(?:www\.)?twitter\.com\/\w+\/timelines\/(\d+)/i,f=/^https?:\/\/(?:www\.)?twitter\.com\/i\/moments\/(\d+)/i,l=/^https?:\/\/(?:www\.)?twitter\.com\/(\w+)\/(?:likes|favorites)/i,h=/^https?:\/\/(?:www\.)?twitter\.com\/(\w+)\/lists\/([\w-%]+)/i,p=/^https?:\/\/(?:www\.)?twitter\.com\/i\/live\/(\d+)/i,m=/^https?:\/\/syndication\.twitter\.com\/settings/i,v=/^https?:\/\/(localhost|platform)\.twitter\.com(?::\d+)?\/widgets\/widget_iframe\.(.+)/i,g=/^https?:\/\/(?:www\.)?twitter\.com\/search\?q=(\w+)/i;function w(t){return"string"==typeof t&&i.test(t)&&RegExp.$1.length<=20}function y(t){if(w(t))return RegExp.$1}function b(t,e){var n=r.decodeURL(t);if(e=e||!1,n.screen_name=y(t),n.screen_name)return r.url("https://twitter.com/intent/"+(e?"follow":"user"),n)}function _(t){return"string"==typeof t&&u.test(t)}function E(t){return"string"==typeof t&&o.test(t)}t.exports={isHashTag:_,hashTag:function(t,e){if(e=void 0===e||e,_(t))return(e?"#":"")+RegExp.$1},isScreenName:w,screenName:y,isStatus:E,status:function(t){return E(t)&&RegExp.$1},intentForProfileURL:b,intentForFollowURL:function(t){return b(t,!0)},isTwitterURL:function(t){return s.test(t)},isTwimgURL:function(t){return a.test(t)},isIntentURL:function(t){return c.test(t)},isSettingsURL:function(t){return m.test(t)},isWidgetIframeURL:function(t){return v.test(t)},isSearchUrl:function(t){return g.test(t)},regexen:{profile:i},momentId:function(t){return f.test(t)&&RegExp.$1},collectionId:function(t){return d.test(t)&&RegExp.$1},intentType:function(t){return c.test(t)&&RegExp.$1},likesScreenName:function(t){return l.test(t)&&RegExp.$1},listScreenNameAndSlug:function(t){var e,n,r;if(h.test(t)){e=RegExp.$1,n=RegExp.$2;try{r=decodeURIComponent(n)}catch(t){}return{ownerScreenName:e,slug:r||n}}return!1},eventId:function(t){return p.test(t)&&RegExp.$1}}},function(t,e){t.exports=document},function(t,e,n){var r=n(0),i=[!0,1,"1","on","ON","true","TRUE","yes","YES"],o=[!1,0,"0","off","OFF","false","FALSE","no","NO"];function s(t){return void 0!==t&&null!==t&&""!==t}function a(t){return c(t)&&t%1==0}function u(t){return c(t)&&!a(t)}function c(t){return s(t)&&!isNaN(t)}function d(t){return r.contains(o,t)}function f(t){return r.contains(i,t)}t.exports={hasValue:s,isInt:a,isFloat:u,isNumber:c,isString:function(t){return"string"===r.toType(t)},isArray:function(t){return s(t)&&"array"==r.toType(t)},isTruthValue:f,isFalseValue:d,asInt:function(t){if(a(t))return parseInt(t,10)},asFloat:function(t){if(u(t))return t},asNumber:function(t){if(c(t))return t},asBoolean:function(t){return!(!s(t)||!f(t)&&(d(t)||!t))}}},function(t,e,n){var r=n(1),i=n(22),o=n(48);i.hasPromiseSupport()||(r.Promise=o),t.exports=r.Promise},function(t,e,n){var r=n(0);t.exports=function(t,e){var n=Array.prototype.slice.call(arguments,2);return function(){var i=r.toRealArray(arguments);return t.apply(e,n.concat(i))}}},function(t,e){t.exports=location},function(t,e,n){var r=n(50);t.exports=new r("__twttr")},function(t,e,n){var r=n(0),i=/\b([\w-_]+)\b/g;function o(t){return new RegExp("\\b"+t+"\\b","g")}function s(t,e){t.classList?t.classList.add(e):o(e).test(t.className)||(t.className+=" "+e)}function a(t,e){t.classList?t.classList.remove(e):t.className=t.className.replace(o(e)," ")}function u(t,e){return t.classList?t.classList.contains(e):r.contains(c(t),e)}function c(t){return r.toRealArray(t.classList?t.classList:t.className.match(i))}t.exports={add:s,remove:a,replace:function(t,e,n){if(t.classList&&u(t,e))return a(t,e),void s(t,n);t.className=t.className.replace(o(e),n)},toggle:function(t,e,n){return void 0===n&&t.classList&&t.classList.toggle?t.classList.toggle(e,n):(n?s(t,e):a(t,e),n)},present:u,list:c}},function(t,e,n){var r=n(5),i=n(0);function o(t){return encodeURIComponent(t).replace(/\+/g,"%2B").replace(/'/g,"%27")}function s(t){return decodeURIComponent(t)}function a(t){var e=[];return i.forIn(t,function(t,n){var s=o(t);i.isType("array",n)||(n=[n]),n.forEach(function(t){r.hasValue(t)&&e.push(s+"="+o(t))})}),e.sort().join("&")}function u(t){var e={};return t?(t.split("&").forEach(function(t){var n=t.split("="),r=s(n[0]),o=s(n[1]);if(2==n.length){if(!i.isType("array",e[r]))return r in e?(e[r]=[e[r]],void e[r].push(o)):void(e[r]=o);e[r].push(o)}}),e):{}}t.exports={url:function(t,e){return a(e).length>0?i.contains(t,"?")?t+"&"+a(e):t+"?"+a(e):t},decodeURL:function(t){var e=t&&t.split("?");return 2==e.length?u(e[1]):{}},decode:u,encode:a,encodePart:o,decodePart:s}},function(t,e,n){var r=n(8),i=n(1),o=n(0),s={},a=o.contains(r.href,"tw_debug=true");function u(){}function c(){}function d(){return i.performance&&+i.performance.now()||+new Date}function f(t,e){if(i.console&&i.console[t])switch(e.length){case 1:i.console[t](e[0]);break;case 2:i.console[t](e[0],e[1]);break;case 3:i.console[t](e[0],e[1],e[2]);break;case 4:i.console[t](e[0],e[1],e[2],e[3]);break;case 5:i.console[t](e[0],e[1],e[2],e[3],e[4]);break;default:0!==e.length&&i.console.warn&&i.console.warn("too many params passed to logger."+t)}}t.exports={devError:u,devInfo:c,devObject:function(t,e){},publicError:function(){f("error",o.toRealArray(arguments))},publicLog:function(){f("info",o.toRealArray(arguments))},time:function(t){a&&(s[t]=d())},timeEnd:function(t){a&&s[t]&&(d(),s[t])}}},function(t,e,n){var r=n(20),i=n(5),o=n(11),s=n(0),a=n(119);t.exports=function(t){var e=t.href&&t.href.split("?")[1],n=e?o.decode(e):{},u={lang:a(t),width:t.getAttribute("data-width")||t.getAttribute("width"),height:t.getAttribute("data-height")||t.getAttribute("height"),related:t.getAttribute("data-related"),partner:t.getAttribute("data-partner")};return i.asBoolean(t.getAttribute("data-dnt"))&&r.setOn(),s.forIn(u,function(t,e){var r=n[t];n[t]=i.hasValue(r)?r:e}),s.compact(n)}},function(t,e,n){var r=n(81),i=n(24);t.exports=function(){var t="data-twitter-extracted-"+i.generate();return function(e,n){return r(e,n).filter(function(e){return!e.hasAttribute(t)}).map(function(e){return e.setAttribute(t,"true"),e})}}},function(t,e){function n(t,e,n,r,i,o,s){this.factory=t,this.Sandbox=e,this.srcEl=o,this.targetEl=i,this.parameters=r,this.className=n,this.options=s}n.prototype.destroy=function(){this.srcEl=this.targetEl=null},t.exports=n},function(t,e){t.exports={DM_BUTTON:"twitter-dm-button",FOLLOW_BUTTON:"twitter-follow-button",HASHTAG_BUTTON:"twitter-hashtag-button",MENTION_BUTTON:"twitter-mention-button",MOMENT:"twitter-moment",PERISCOPE:"periscope-on-air",SHARE_BUTTON:"twitter-share-button",TIMELINE:"twitter-timeline",TWEET:"twitter-tweet"}},function(t,e,n){var r=n(6),i=n(20),o=n(52),s=n(36),a=n(5),u=n(0);t.exports=function(t,e,n){var c;return t=t||[],e=e||{},c="ƒ("+t.join(", ")+", target, [options]);",function(){var d,f,l,h,p=Array.prototype.slice.apply(arguments,[0,t.length]),m=Array.prototype.slice.apply(arguments,[t.length]);return m.forEach(function(t){t&&(t.nodeType!==Node.ELEMENT_NODE?u.isType("function",t)?d=t:u.isType("object",t)&&(f=t):l=t)}),p.length!==t.length||0===m.length?(d&&u.async(function(){d(!1)}),r.reject(new Error("Not enough parameters. Expected: "+c))):l?(f=u.aug({},f||{},e),t.forEach(function(t){f[t]=p.shift()}),a.asBoolean(f.dnt)&&i.setOn(),h=s.getExperiments().then(function(t){return o.addWidget(n(f,l,void 0,t))}),d&&h.then(d,function(){d(!1)}),h):(d&&u.async(function(){d(!1)}),r.reject(new Error("No target element specified. Expected: "+c)))}}},function(t,e,n){var r=n(102),i=n(2),o=n(0);function s(t,e){return function(){try{e.resolve(t.call(this))}catch(t){e.reject(t)}}}t.exports={sync:function(t,e){t.call(e)},read:function(t,e){var n=new i;return r.read(s(t,n),e),n.promise},write:function(t,e){var n=new i;return r.write(s(t,n),e),n.promise},defer:function(t,e,n){var a=new i;return o.isType("function",t)&&(n=e,e=t,t=1),r.defer(t,s(e,a),n),a.promise}}},function(t,e,n){var r=n(9),i=["https://syndication.twitter.com","https://cdn.syndication.twimg.com","https://localhost.twitter.com:8444"],o=["https://syndication.twitter.com","https://localhost.twitter.com:8445"],s=["https://platform.twitter.com/embed/index.html","https://localhost.twitter.com",/https:\/\/ton\.smf1\.twitter\.com\/syndication-internal\/embed-iframe\/[0-9A-Za-z_-]+\/app\/index\.html/],a=function(t,e){return t.some(function(t){return t instanceof RegExp?t.test(e):t===e})},u=function(){var t=r.get("backendHost");return t&&a(i,t)?t:"https://cdn.syndication.twimg.com"},c=function(){var t=r.get("settingsSvcHost");return t&&a(o,t)?t:"https://syndication.twitter.com"},d=function(){var t=r.get("embedIframeURL");return t&&a(s,t)?t:"https://platform.twitter.com/embed/index.html"};function f(t,e){var n=[t];return e.forEach(function(t){n.push(function(t){var e=(t||"").toString(),n="/"===e.slice(0,1)?1:0,r=function(t){return"/"===t.slice(-1)}(e)?-1:void 0;return e.slice(n,r)}(t))}),n.join("/")}t.exports={cookieConsent:function(t){var e=t||[];return e.unshift("cookie/consent"),f(c(),e)},embedIframe:function(){return d()},eventVideo:function(t){var e=t||[];return e.unshift("video/event"),f(u(),e)},grid:function(t){var e=t||[];return e.unshift("grid/collection"),f(u(),e)},moment:function(t){var e=t||[];return e.unshift("moments"),f(u(),e)},settings:function(t){var e=t||[];return e.unshift("settings"),f(c(),e)},timeline:function(t){var e=t||[];return e.unshift("timeline"),f(u(),e)},tweetBatch:function(t){var e=t||[];return e.unshift("tweets.json"),f(u(),e)},video:function(t){var e=t||[];return e.unshift("widgets/video"),f(u(),e)}}},function(t,e,n){var r=n(4),i=n(8),o=n(35),s=n(79),a=n(5),u=n(34),c=!1,d=/https?:\/\/([^/]+).*/i;t.exports={setOn:function(){c=!0},enabled:function(t,e){return!!(c||a.asBoolean(u.val("dnt"))||s.isUrlSensitive(e||i.host)||o.isFramed()&&s.isUrlSensitive(o.rootDocumentLocation())||(t=d.test(t||r.referrer)&&RegExp.$1)&&s.isUrlSensitive(t))}}},function(t,e,n){var r=n(47),i=n(4),o=n(20),s=n(33),a=n(71),u=n(32),c=n(9),d=n(3),f=n(0),l=1,h=r.version,p=c.get("clientEventEndpoint")||"https://syndication.twitter.com/i/jot";function m(t){return f.aug({client:"tfw"},t||{})}function v(t,e,n){return e=e||{},f.aug({},e,{_category_:t,triggered_on:e.triggered_on||+new Date,dnt:o.enabled(n)})}t.exports={extractTermsFromDOM:function t(e,n){var r;return n=n||{},e&&e.nodeType===Node.ELEMENT_NODE?((r=e.getAttribute("data-scribe"))&&r.split(" ").forEach(function(t){var e=t.trim().split(":"),r=e[0],i=e[1];r&&i&&!n[r]&&(n[r]=i)}),t(e.parentNode,n)):n},clickEventElement:function(t){var e=s.closest("[data-expanded-url]",t),n=e&&e.getAttribute("data-expanded-url");return n&&d.isTwitterURL(n)?"twitter_url":"url"},flattenClientEventPayload:function(t,e){return f.aug({},e,{event_namespace:t})},formatGenericEventData:v,formatClientEventData:function(t,e,n){var r=t&&t.widget_origin||i.referrer;return(t=v("tfw_client_event",t,r)).client_version=h,t.format_version=void 0!==n?n:1,e||(t.widget_origin=r),t},formatClientEventNamespace:m,formatHorizonTweetData:function(t){var e={item_ids:[],item_details:{}};return e.item_ids.push(t),e.item_details[t]={item_type:a.TWEET},e},formatTweetAssociation:function(t,e){var n={};return(e=e||{}).association_namespace=m(t),n[l]=e,n},noticeSeen:function(t){return"notice"===t.element&&"seen"===t.action},splitLogEntry:function(t){var e,n,r,i,o;return t.item_ids&&t.item_ids.length>1?(e=Math.floor(t.item_ids.length/2),n=t.item_ids.slice(0,e),r={},i=t.item_ids.slice(e),o={},n.forEach(function(e){r[e]=t.item_details[e]}),i.forEach(function(e){o[e]=t.item_details[e]}),[f.aug({},t,{item_ids:n,item_details:r}),f.aug({},t,{item_ids:i,item_details:o})]):[t]},stringify:function(t){var e,n=Array.prototype.toJSON;return delete Array.prototype.toJSON,e=u.stringify(t),n&&(Array.prototype.toJSON=n),e},AUDIENCE_ENDPOINT:"https://syndication.twitter.com/i/jot/syndication",CLIENT_EVENT_ENDPOINT:p,RUFOUS_REDIRECT:"https://platform.twitter.com/jot.html"}},function(t,e,n){var r=n(4),i=n(12),o=n(96),s=n(1),a=n(0),u=o.userAgent;function c(t){return/(Trident|MSIE|Edge[/ ]?\d)/.test(t=t||u)}t.exports={retina:function(t){return(t=t||s).devicePixelRatio?t.devicePixelRatio>=1.5:!!t.matchMedia&&t.matchMedia("only screen and (min-resolution: 144dpi)").matches},anyIE:c,ie9:function(t){return/MSIE 9/.test(t=t||u)},ie10:function(t){return/MSIE 10/.test(t=t||u)},ios:function(t){return/(iPad|iPhone|iPod)/.test(t=t||u)},android:function(t){return/^Mozilla\/5\.0 \(Linux; (U; )?Android/.test(t=t||u)},canPostMessage:function(t,e){return t=t||s,e=e||u,t.postMessage&&!(c(e)&&t.opener)},touch:function(t,e,n){return t=t||s,e=e||o,n=n||u,"ontouchstart"in t||/Opera Mini/.test(n)||e.msMaxTouchPoints>0},cssTransitions:function(){var t=r.body.style;return void 0!==t.transition||void 0!==t.webkitTransition||void 0!==t.mozTransition||void 0!==t.oTransition||void 0!==t.msTransition},hasPromiseSupport:function(){return!!(s.Promise&&s.Promise.resolve&&s.Promise.reject&&s.Promise.all&&s.Promise.race&&(new s.Promise(function(e){t=e}),a.isType("function",t)));var t},hasIntersectionObserverSupport:function(){return!!s.IntersectionObserver},hasPerformanceInformation:function(){return s.performance&&s.performance.getEntriesByType},hasLocalStorageSupport:function(){try{return s.localStorage.setItem("local_storage_support_test","true"),void 0!==s.localStorage}catch(t){return i.devError("window.localStorage is not supported:",t),!1}}}},function(t,e,n){var r=n(6),i=n(2);function o(t,e){return t.then(e,e)}function s(t){return t instanceof r}t.exports={always:o,allResolved:function(t){var e;return void 0===t?r.reject(new Error("undefined is not an object")):Array.isArray(t)?(e=t.length)?new r(function(n,r){var i=0,o=[];function a(){(i+=1)===e&&(0===o.length?r():n(o))}function u(t){o.push(t),a()}t.forEach(function(t){s(t)?t.then(u,a):u(t)})}):r.resolve([]):r.reject(new Error("Type error"))},some:function(t){var e;return e=(t=t||[]).length,t=t.filter(s),e?e!==t.length?r.reject("non-Promise passed to .some"):new r(function(e,n){var r=0;function i(){(r+=1)===t.length&&n()}t.forEach(function(t){t.then(e,i)})}):r.reject("no promises passed to .some")},isPromise:s,allSettled:function(t){function e(){}return r.all((t||[]).map(function(t){return o(t,e)}))},timeout:function(t,e){var n=new i;return setTimeout(function(){n.reject(new Error("Promise timed out"))},e),t.then(function(t){n.resolve(t)},function(t){n.reject(t)}),n.promise}}},function(t,e){var n="i",r=0,i=0;t.exports={generate:function(){return n+String(+new Date)+Math.floor(1e5*Math.random())+r++},deterministic:function(){return n+String(i++)}}},function(t,e,n){var r=n(49),i=n(51),o=n(0);t.exports=o.aug(r.get("events")||{},i.Emitter)},function(t,e,n){var r=n(27),i=n(110);t.exports=r.build([i])},function(t,e,n){var r=n(40),i=n(107),o=n(7);(r=Object.create(r)).build=o(r.build,null,i),t.exports=r},function(t,e,n){var r=n(40),i=n(41),o=n(7);(r=Object.create(r)).build=o(r.build,null,i),t.exports=r},function(t,e,n){var r=n(83),i=n(75),o=n(84),s=n(8),a=n(70),u=n(74),c=n(20),d=n(5),f=n(24),l=n(0);function h(t){if(!t||!t.headers)throw new Error("unexpected response schema");return{html:t.body,config:t.config,pollInterval:1e3*parseInt(t.headers.xPolling,10)||null,maxCursorPosition:t.headers.maxPosition,minCursorPosition:t.headers.minPosition}}function p(t){if(t&&t.headers)throw new Error(t.headers.status);throw t instanceof Error?t:new Error(t)}t.exports=function(t){t.params({instanceId:{required:!0,fallback:f.deterministic},lang:{required:!0,transform:a.matchLanguage,fallback:"en"},tweetLimit:{transform:d.asInt}}),t.defineProperty("endpoint",{get:function(){throw new Error("endpoint not specified")}}),t.defineProperty("pollEndpoint",{get:function(){return this.endpoint}}),t.define("cbId",function(t){var e=t?"_new":"_old";return"tl_"+this.params.instanceId+"_"+this.id+e}),t.define("queryParams",function(){return{lang:this.params.lang,tz:u.getTimezoneOffset(),t:r(),domain:s.host,tweet_limit:this.params.tweetLimit,dnt:c.enabled()}}),t.define("fetch",function(){return i.fetch(this.endpoint,this.queryParams(),o,this.cbId()).then(h,p)}),t.define("poll",function(t,e){var n,r;return n={since_id:(t=t||{}).sinceId,max_id:t.maxId,min_position:t.minPosition,max_position:t.maxPosition},r=l.aug(this.queryParams(),n),i.fetch(this.pollEndpoint,r,o,this.cbId(e)).then(h,p)})}},function(t,e,n){var r=n(51).makeEmitter();t.exports={emitter:r,START:"start",ALL_WIDGETS_RENDER_START:"all_widgets_render_start",ALL_WIDGETS_RENDER_END:"all_widgets_render_end",ALL_WIDGETS_AND_IMAGES_LOADED:"all_widgets_and_images_loaded"}},function(t,e,n){var r=n(4),i=n(0);t.exports=function(t,e,n){var o;if(n=n||r,t=t||{},e=e||{},t.name){try{o=n.createElement('')}catch(e){(o=n.createElement("iframe")).name=t.name}delete t.name}else o=n.createElement("iframe");return t.id&&(o.id=t.id,delete t.id),o.allowtransparency="true",o.scrolling="no",o.setAttribute("frameBorder",0),o.setAttribute("allowTransparency",!0),i.forIn(t,function(t,e){o.setAttribute(t,e)}),i.forIn(e,function(t,e){o.style[t]=e}),o}},function(t,e,n){var r=n(1).JSON;t.exports={stringify:r.stringify||r.encode,parse:r.parse||r.decode}},function(t,e,n){var r=n(0),i=n(43);t.exports={closest:function t(e,n,o){var s;if(n)return o=o||n&&n.ownerDocument,s=r.isType("function",e)?e:function(t){return function(e){return!!e.tagName&&i(e,t)}}(e),n===o?s(n)?n:void 0:s(n)?n:t(s,n.parentNode,o)}}},function(t,e,n){var r,i=n(4);function o(t){var e,n,o,s=0;for(r={},e=(t=t||i).getElementsByTagName("meta");e[s];s++){if(n=e[s],/^twitter:/.test(n.getAttribute("name")))o=n.getAttribute("name").replace(/^twitter:/,"");else{if(!/^twitter:/.test(n.getAttribute("property")))continue;o=n.getAttribute("property").replace(/^twitter:/,"")}r[o]=n.getAttribute("content")||n.getAttribute("value")}}o(),t.exports={init:o,val:function(t){return r[t]}}},function(t,e,n){var r=n(8),i=n(78),o=n(0),s=i.getCanonicalURL()||r.href,a=s;t.exports={isFramed:function(){return s!==a},rootDocumentLocation:function(t){return t&&o.isType("string",t)&&(s=t),s},currentDocumentLocation:function(){return a}}},function(t,e,n){var r=n(113),i=n(116);function o(t){return r.settingsLoaded().then(function(e){return e[t]})}function s(){return o("experiments")}t.exports={shouldObtainCookieConsent:function(){return o("shouldObtainCookieConsent")},getExperiments:s,getExperiment:function(t){return s().then(function(e){if(!e[t])throw new Error("Experiment not found");return e[t]})},getActiveExperimentDataString:function(){return s().then(function(t){var e=Object.keys(t).reduce(function(e,n){var r;return t[n].version&&(r=n.split("_").slice(-1)[0],e.push(r+";"+t[n].bucket)),e},[]);return i(e.join(","))})},getExperimentKeys:function(){return s().then(function(t){return Object.keys(t)})},load:function(){r.load()}}},function(t,e,n){var r=n(10),i={},o=-1,s={};function a(t){var e=t.getAttribute("data-twitter-event-id");return e||(t.setAttribute("data-twitter-event-id",++o),o)}function u(t,e,n){var r=0,i=t&&t.length||0;for(r=0;r0&&(n=n.slice(0,1),o.canFlushOneItem(n[0])||(n[0].input.data.message=""),c(n)),a&&(u(a)?c:function(t){i.init(),t.forEach(function(t){var e=t.input.namespace,n=t.input.data,r=t.input.offsite,o=t.input.version;i.clientEvent(e,n,r,o)}),i.flush().then(function(){t.forEach(function(t){t.taskDoneDeferred.resolve()})},function(){t.forEach(function(t){t.taskDoneDeferred.reject()})})})(a)}});function u(t){return 1===t.length&&o.canFlushOneItem(t[0])}function c(t){t.forEach(function(t){var e=t.input.namespace,n=t.input.data,r=t.input.offsite,i=t.input.version;o.clientEvent(e,n,r,i),t.taskDoneDeferred.resolve()})}t.exports={scribe:function(t,e,n,r){return a.add({namespace:t,data:e,offsite:n,version:r})},pause:function(){a.pause()},resume:function(){a.resume()}}},function(t,e,n){var r=n(27),i=n(125);t.exports=r.build([i])},function(t,e,n){var r=n(105),i=n(106),o=n(0);t.exports={couple:function(){return o.toRealArray(arguments)},build:function(t,e,n){var o=new t;return(e=i(r(e||[]))).forEach(function(t){t.call(null,o)}),o.build(n)}}},function(t,e,n){var r=n(108),i=n(0),o=n(42);function s(){this.Component=this.factory(),this._adviceArgs=[],this._lastArgs=[]}i.aug(s.prototype,{factory:o,build:function(t){var e=this;return this.Component,i.aug(this.Component.prototype.boundParams,t),this._adviceArgs.concat(this._lastArgs).forEach(function(t){(function(t,e,n){var r=this[e];if(!r)throw new Error(e+" does not exist");this[e]=t(r,n)}).apply(e.Component.prototype,t)}),delete this._lastArgs,delete this._adviceArgs,this.Component},params:function(t){var e=this.Component.prototype.paramConfigs;t=t||{},this.Component.prototype.paramConfigs=i.aug({},t,e)},define:function(t,e){if(t in this.Component.prototype)throw new Error(t+" has previously been defined");this.override(t,e)},defineStatic:function(t,e){this.Component[t]=e},override:function(t,e){this.Component.prototype[t]=e},defineProperty:function(t,e){if(t in this.Component.prototype)throw new Error(t+" has previously been defined");this.overrideProperty(t,e)},overrideProperty:function(t,e){var n=i.aug({configurable:!0},e);Object.defineProperty(this.Component.prototype,t,n)},before:function(t,e){this._adviceArgs.push([r.before,t,e])},after:function(t,e){this._adviceArgs.push([r.after,t,e])},around:function(t,e){this._adviceArgs.push([r.around,t,e])},last:function(t,e){this._lastArgs.push([r.after,t,e])}}),t.exports=s},function(t,e,n){var r=n(0);function i(){return!0}function o(t){return t}t.exports=function(){function t(t){var e=this;t=t||{},this.params=Object.keys(this.paramConfigs).reduce(function(n,s){var a=[],u=e.boundParams,c=e.paramConfigs[s],d=c.validate||i,f=c.transform||o;if(s in u&&a.push(u[s]),s in t&&a.push(t[s]),a="fallback"in c?a.concat(c.fallback):a,n[s]=function(t,e,n){var i=null;return t.some(function(t){if(t=r.isType("function",t)?t():t,e(t))return i=n(t),!0}),i}(a,d,f),c.required&&null==n[s])throw new Error(s+" is a required parameter");return n},{}),this.initialize()}return r.aug(t.prototype,{paramConfigs:{},boundParams:{},initialize:function(){}}),t}},function(t,e,n){var r=n(1).HTMLElement,i=r.prototype.matches||r.prototype.matchesSelector||r.prototype.webkitMatchesSelector||r.prototype.mozMatchesSelector||r.prototype.msMatchesSelector||r.prototype.oMatchesSelector;t.exports=function(t,e){if(i)return i.call(t,e)}},function(t,e,n){var r,i=n(10),o=n(4),s=n(1),a=n(34),u=n(53),c=n(5),d=n(24),f="csptest";t.exports={inlineStyle:function(){var t=f+d.generate(),e=o.createElement("div"),n=o.createElement("style"),l="."+t+" { visibility: hidden; }";return!!o.body&&(c.asBoolean(a.val("widgets:csp"))&&(r=!1),void 0!==r?r:(e.style.display="none",i.add(e,t),n.type="text/css",n.appendChild(o.createTextNode(l)),o.body.appendChild(n),o.body.appendChild(e),r="hidden"===s.getComputedStyle(e).visibility,u(e),u(n),r))}}},function(t,e,n){var r=n(1);t.exports=function(t,e,n){var i,o=0;return n=n||null,function s(){var a=n||this,u=arguments,c=+new Date;if(r.clearTimeout(i),c-o>e)return o=c,void t.apply(a,u);i=r.setTimeout(function(){s.apply(a,u)},e)}}},function(t,e){t.exports=function(t){var e=t.getBoundingClientRect();return{width:e.width,height:e.height}}},function(t){t.exports={version:"3f79a62:1592980045844"}},function(t,e,n){ +/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version v4.2.5+7f2b526d + */var r;r=function(){"use strict";function t(t){return"function"==typeof t}var e=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},n=0,r=void 0,i=void 0,o=function(t,e){l[n]=t,l[n+1]=e,2===(n+=2)&&(i?i(h):w())},s="undefined"!=typeof window?window:void 0,a=s||{},u=a.MutationObserver||a.WebKitMutationObserver,c="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),d="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function f(){var t=setTimeout;return function(){return t(h,1)}}var l=new Array(1e3);function h(){for(var t=0;t=0&&this._handlers[t].splice(n,1):this._handlers[t]=[])},trigger:function(t,e){var n=this._handlers&&this._handlers[t];(e=e||{}).type=t,n&&n.forEach(function(t){r.async(i(t,this,e))})}};t.exports={Emitter:o,makeEmitter:function(){return r.aug(function(){},o)}}},function(t,e,n){var r=n(101),i=n(76),o=n(6),s=n(23),a=n(7),u=n(0),c=new i(function(t){var e=function(t){return t.reduce(function(t,e){return t[e._className]=t[e._className]||[],t[e._className].push(e),t},{})}(t.map(r.fromRawTask));u.forIn(e,function(t,e){s.allSettled(e.map(function(t){return t.initialize()})).then(function(){e.forEach(function(t){o.all([t.hydrate(),t.insertIntoDom()]).then(a(t.render,t)).then(a(t.success,t),a(t.fail,t))})})})});t.exports={addWidget:function(t){return c.add(t)}}},function(t,e,n){var r=n(18);t.exports=function(t){return r.write(function(){t&&t.parentNode&&t.parentNode.removeChild(t)})}},function(t,e,n){n(12),t.exports={log:function(t,e){}}},function(t,e,n){var r=n(1);function i(t){return(t=t||r).getSelection&&t.getSelection()}t.exports={getSelection:i,getSelectedText:function(t){var e=i(t);return e?e.toString():""}}},function(t,e,n){var r=n(4),i=n(1),o=n(2),s=2e4;t.exports=function(t){var e=new o,n=r.createElement("img");return n.onload=n.onerror=function(){i.setTimeout(e.resolve,50)},n.src=t,i.setTimeout(e.reject,s),e.promise}},function(t,e,n){var r=n(111);t.exports=function(t){t.define("createElement",r),t.define("createFragment",r),t.define("htmlToElement",r),t.define("hasSelectedText",r),t.define("addRootClass",r),t.define("removeRootClass",r),t.define("hasRootClass",r),t.define("prependStyleSheet",r),t.define("appendStyleSheet",r),t.define("prependCss",r),t.define("appendCss",r),t.define("makeVisible",r),t.define("injectWidgetEl",r),t.define("matchHeightToContent",r),t.define("matchWidthToContent",r)}},function(t,e){t.exports=function(t){var e,n=!1;return function(){return n?e:(n=!0,e=t.apply(this,arguments))}}},function(t,e,n){var r=n(15),i=n(120),o=n(60),s=n(16);t.exports=function(t,e,n){return new r(i,o,s.DM_BUTTON,t,e,n)}},function(t,e,n){var r=n(61),i=n(26);t.exports=r.isSupported()?r:i},function(t,e,n){var r=n(27),i=n(121);t.exports=r.build([i])},function(t,e,n){var r=n(15),i=n(124),o=n(39),s=n(16);t.exports=function(t,e,n){return new r(i,o,s.FOLLOW_BUTTON,t,e,n)}},function(t,e,n){var r=n(15),i=n(132),o=n(26),s=n(16);t.exports=function(t,e,n){return new r(i,o,s.MOMENT,t,e,n)}},function(t,e,n){var r=n(15),i=n(134),o=n(26),s=n(16);t.exports=function(t,e,n){return new r(i,o,s.PERISCOPE,t,e,n)}},function(t,e,n){var r=n(82),i=n(136),o=n(140),s=n(142),a=n(144),u=n(146),c={collection:i,event:o,likes:s,list:a,profile:u,url:f},d=[u,s,i,a,o];function f(t){return r(d,function(e){try{return new e(t)}catch(t){}})}t.exports=function(t){return t?function(t){var e,n;return e=(t.sourceType+"").toLowerCase(),(n=c[e])?new n(t):null}(t)||f(t):null}},function(t,e,n){var r=n(15),i=n(148),o=n(26),s=n(16);t.exports=function(t,e,n){return new r(i,o,s.TIMELINE,t,e,n)}},function(t,e,n){var r=n(4),i=n(150),o=n(152),s=n(15),a=n(39),u=n(153),c=n(60),d=n(154),f=n(16);t.exports=function(t,e,n,l){var h,p=i.isHorizonTweetEnabled(l,t);return o(l,t.tweetId),p?(h=r.createElement("div"),new s(u,a,f.TWEET,t,e,n,{sandboxWrapperEl:h})):new s(d,c,f.TWEET,t,e,n)}},function(t,e,n){var r=n(15),i=n(156),o=n(39),s=n(16);t.exports=function(t,e,n){var a=t&&t.type||"share",u="hashtag"==a?s.HASHTAG_BUTTON:"mention"==a?s.MENTION_BUTTON:s.SHARE_BUTTON;return new r(i,o,u,t,e,n)}},function(t,e,n){var r=n(38),i=n(35),o=n(0);t.exports=function(t){var e={widget_origin:i.rootDocumentLocation(),widget_frame:i.isFramed()?i.currentDocumentLocation():null,duration_ms:t.duration,item_ids:t.widgetIds||[]},n=o.aug(t.namespace,{page:"page",component:"performance"});r.scribe(n,e)}},function(t,e,n){var r=n(0),i=n(137),o=["ar","fa","he","ur"];t.exports={isRtlLang:function(t){return t=String(t).toLowerCase(),r.contains(o,t)},matchLanguage:function(t){return t=(t=(t||"").toLowerCase()).replace("_","-"),i(t)?t:(t=t.replace(/-.*/,""),i(t)?t:"en")}}},function(t){t.exports={TWEET:0,RETWEET:10,CUSTOM_TIMELINE:17,LIVE_VIDEO_EVENT:28,QUOTE_TWEET:23}},function(t){t.exports={tweetButtonHtmlPath:"/widgets/tweet_button.0b18cf62dd2a99c3b87d3915abc4ade2.{{lang}}.html",followButtonHtmlPath:"/widgets/follow_button.0b18cf62dd2a99c3b87d3915abc4ade2.{{lang}}.html",hubHtmlPath:"/widgets/hub.html",widgetIframeHtmlPath:"/widgets/widget_iframe.0b18cf62dd2a99c3b87d3915abc4ade2.html",resourceBaseUrl:"https://platform.twitter.com"}},function(t,e,n){var r=n(3),i=n(99),o=n(25),s=n(11),a={favorite:["favorite","like"],follow:["follow"],like:["favorite","like"],retweet:["retweet"],tweet:["tweet"]};function u(t){this.srcEl=[],this.element=t}u.open=function(t,e,n){var u=(r.intentType(t)||"").toLowerCase();r.isTwitterURL(t)&&(function(t,e){i.open(t,e)}(t,n),e&&o.trigger("click",{target:e,region:"intent",type:"click",data:{}}),e&&a[u]&&a[u].forEach(function(n){o.trigger(n,{target:e,region:"intent",type:n,data:function(t,e){var n=s.decodeURL(e);switch(t){case"favorite":case"like":return{tweet_id:n.tweet_id};case"follow":return{screen_name:n.screen_name,user_id:n.user_id};case"retweet":return{source_tweet_id:n.tweet_id};default:return{}}}(u,t)})}))},t.exports=u},function(t,e){t.exports={getTimezoneOffset:function(){var t=(new Date).toString().match(/(GMT[+-]?\d+)/);return t&&t[0]||"GMT"}}},function(t,e,n){var r=n(4),i=n(9),o=n(2),s=n(0),a=n(11),u="cb",c=0;t.exports={fetch:function(t,e,n,d){var f,l,h;return d=function(t){if(t)return t.replace(/[^\w$]/g,"_")}(d||u+c++),f=i.fullPath(["callbacks",d]),l=r.createElement("script"),h=new o,e=s.aug({},e,{callback:f,suppress_response_codes:!0}),i.set(["callbacks",d],function(t){var e;t=(e=n(t||!1)).resp,e.success?h.resolve(t):h.reject(t),l.onload=l.onreadystatechange=null,l.parentNode&&l.parentNode.removeChild(l),i.unset(["callbacks",d])}),l.onerror=function(){h.reject(new Error("failed to fetch "+l.src))},l.src=a.url(t,e),l.async="async",r.body.appendChild(l),h.promise}}},function(t,e,n){var r=n(2),i=n(103),o=n(7);function s(t){this._inputsQueue=[],this._task=t,this._hasFlushBeenScheduled=!1}s.prototype.add=function(t){var e=new r;return this._inputsQueue.push({input:t,taskDoneDeferred:e}),this._hasFlushBeenScheduled||(this._hasFlushBeenScheduled=!0,i(o(this._flush,this))),e.promise},s.prototype._flush=function(){try{this._task.call(null,this._inputsQueue)}catch(t){this._inputsQueue.forEach(function(e){e.taskDoneDeferred.reject(t)})}this._inputsQueue=[],this._hasFlushBeenScheduled=!1},t.exports=s},function(t,e){t.exports=function(t,e){return t.reduce(function(t,n){var r=e(n);return t[r]=t[r]||[],t[r].push(n),t},{})}},function(t,e,n){var r=n(4),i=n(8),o=n(3);function s(t,e){var n,r;return e=e||i,/^https?:\/\//.test(t)?t:/^\/\//.test(t)?e.protocol+t:(n=e.host+(e.port.length?":"+e.port:""),0!==t.indexOf("/")&&((r=e.pathname.split("/")).pop(),r.push(t),t="/"+r.join("/")),[e.protocol,"//",n,t].join(""))}t.exports={absolutize:s,getCanonicalURL:function(){for(var t,e=r.getElementsByTagName("link"),n=0;e[n];n++)if("canonical"==(t=e[n]).rel)return s(t.href)},getScreenNameFromPage:function(){for(var t,e,n,i=[r.getElementsByTagName("a"),r.getElementsByTagName("link")],s=0,a=0,u=/\bme\b/;t=i[s];s++)for(a=0;e=t[a];a++)if(u.test(e.rel)&&(n=o.screenName(e.href)))return n}}},function(t,e,n){var r=n(8),i=/^[^#?]*\.(gov|mil)(:\d+)?([#?].*)?$/i,o={};function s(t){return t in o?o[t]:o[t]=i.test(t)}t.exports={isUrlSensitive:s,isHostPageSensitive:function(){return s(r.host)}}},function(t,e,n){var r=n(20),i=n(54),o=n(11),s=n(21),a=n(0),u=n(9).get("scribeCallback"),c=2083,d=[],f=o.url(s.CLIENT_EVENT_ENDPOINT,{dnt:0,l:""}),l=encodeURIComponent(f).length;function h(t,e,n,r){var i=!a.isObject(t),o=!!e&&!a.isObject(e);i||o||(u&&u(arguments),p(s.formatClientEventNamespace(t),s.formatClientEventData(e,n,r),s.CLIENT_EVENT_ENDPOINT))}function p(t,e,n){var r,u;n&&a.isObject(t)&&a.isObject(e)&&(i.log(t,e),r=s.flattenClientEventPayload(t,e),u={l:s.stringify(r)},s.noticeSeen(t)&&(u.notice_seen=!0),r.dnt&&(u.dnt=1),w(o.url(n,u)))}function m(t,e,n,r){var i=!a.isObject(t),o=!!e&&!a.isObject(e);if(!i&&!o)return v(s.flattenClientEventPayload(s.formatClientEventNamespace(t),s.formatClientEventData(e,n,r)))}function v(t){return d.push(t),d}function g(t){return encodeURIComponent(t).length+3}function w(t){return(new Image).src=t}t.exports={canFlushOneItem:function(t){var e=g(s.stringify(t));return l+e1&&m({page:"widgets_js",component:"scribe_pixel",action:"batch_log"},{}),t=d,d=[],t.reduce(function(e,n,r){var i=e.length,o=i&&e[i-1];return r+1==t.length&&n.event_namespace&&"batch_log"==n.event_namespace.action&&(n.message=["entries:"+r,"requests:"+i].join("/")),function t(e){return Array.isArray(e)||(e=[e]),e.reduce(function(e,n){var r,i=s.stringify(n),o=g(i);return l+o1&&(e=e.concat(t(r))),e},[])}(n).forEach(function(t){var n=g(t);(!o||o.urlLength+n>c)&&(o={urlLength:l,items:[]},e.push(o)),o.urlLength+=n,o.items.push(t)}),e},[]).map(function(t){var e={l:t.items};return r.enabled()&&(e.dnt=1),w(o.url(s.CLIENT_EVENT_ENDPOINT,e))})},interaction:function(t,e,n,r){var i=s.extractTermsFromDOM(t.target||t.srcElement);i.action=r||"click",h(i,e,n)}}},function(t,e,n){var r=n(0),i=n(43);t.exports=function(t,e){return i(t,e)?[t]:r.toRealArray(t.querySelectorAll(e))}},function(t,e){t.exports=function(t,e,n){for(var r,i=0;i")}).then(function(){t.close(),a.resolve(c)})}),c.src=["javascript:",'document.write("");',"try { window.parent.document; }",'catch (e) { document.domain="'+r.domain+'"; }',"window.parent."+g.fullPath(["sandbox",u])+"();"].join(""),c.addEventListener("error",a.reject,!1),o.write(function(){i.parentNode.replaceChild(c,i)}),a.promise}t.exports=a.couple(n(57),function(t){t.overrideProperty("id",{get:function(){return this.sandboxEl&&this.sandboxEl.id}}),t.overrideProperty("initialized",{get:function(){return!!this.win}}),t.overrideProperty("width",{get:function(){return this._width}}),t.overrideProperty("height",{get:function(){return this._height}}),t.overrideProperty("sandboxEl",{get:function(){return this.iframeEl}}),t.defineProperty("iframeEl",{get:function(){return this._iframe}}),t.defineProperty("rootEl",{get:function(){return this.doc&&this.doc.documentElement}}),t.defineProperty("widgetEl",{get:function(){return this.doc&&this.doc.body.firstElementChild}}),t.defineProperty("win",{get:function(){return this.iframeEl&&this.iframeEl.contentWindow}}),t.defineProperty("doc",{get:function(){return this.win&&this.win.document}}),t.define("_updateCachedDimensions",function(){var t=this;return o.read(function(){var e,n=h(t.sandboxEl);"visible"==t.sandboxEl.style.visibility?t._width=n.width:(e=h(t.sandboxEl.parentElement).width,t._width=Math.min(n.width,e)),t._height=n.height})}),t.define("_setTargetToBlank",function(){var t=this.createElement("base");t.target="_blank",this.doc.head.appendChild(t)}),t.define("_didResize",function(){var t=this,e=this._resizeHandlers.slice(0);return this._updateCachedDimensions().then(function(){e.forEach(function(e){e(t)})})}),t.define("setTitle",function(t){this.iframeEl.title=t}),t.override("createElement",function(t){return this.doc.createElement(t)}),t.override("createFragment",function(){return this.doc.createDocumentFragment()}),t.override("htmlToElement",function(t){var e;return(e=this.createElement("div")).innerHTML=t,e.firstElementChild}),t.override("hasSelectedText",function(){return!!s.getSelectedText(this.win)}),t.override("addRootClass",function(t){var e=this.rootEl;return t=Array.isArray(t)?t:[t],this.initialized?o.write(function(){t.forEach(function(t){i.add(e,t)})}):m.reject(new Error("sandbox not initialized"))}),t.override("removeRootClass",function(t){var e=this.rootEl;return t=Array.isArray(t)?t:[t],this.initialized?o.write(function(){t.forEach(function(t){i.remove(e,t)})}):m.reject(new Error("sandbox not initialized"))}),t.override("hasRootClass",function(t){return i.present(this.rootEl,t)}),t.define("addStyleSheet",function(t,e){var n,r=new p;return this.initialized?((n=this.createElement("link")).type="text/css",n.rel="stylesheet",n.href=t,n.addEventListener("load",r.resolve,!1),n.addEventListener("error",r.reject,!1),o.write(y(e,null,n)).then(function(){return u(t).then(r.resolve,r.reject),r.promise})):m.reject(new Error("sandbox not initialized"))}),t.override("prependStyleSheet",function(t){var e=this.doc;return this.addStyleSheet(t,function(t){var n=e.head.firstElementChild;return n?e.head.insertBefore(t,n):e.head.appendChild(t)})}),t.override("appendStyleSheet",function(t){var e=this.doc;return this.addStyleSheet(t,function(t){return e.head.appendChild(t)})}),t.define("addCss",function(t,e){var n;return c.inlineStyle()?((n=this.createElement("style")).type="text/css",n.appendChild(this.doc.createTextNode(t)),o.write(y(e,null,n))):(l.devError("CSP enabled; cannot embed inline styles"),m.resolve())}),t.override("prependCss",function(t){var e=this.doc;return this.addCss(t,function(t){var n=e.head.firstElementChild;return n?e.head.insertBefore(t,n):e.head.appendChild(t)})}),t.override("appendCss",function(t){var e=this.doc;return this.addCss(t,function(t){return e.head.appendChild(t)})}),t.override("makeVisible",function(){var t=this;return this.styleSelf(E).then(function(){t._updateCachedDimensions()})}),t.override("injectWidgetEl",function(t){var e=this;return this.initialized?this.widgetEl?m.reject(new Error("widget already injected")):o.write(function(){e.doc.body.appendChild(t)}):m.reject(new Error("sandbox not initialized"))}),t.override("matchHeightToContent",function(){var t,e=this;return o.read(function(){t=e.widgetEl?h(e.widgetEl).height:0}),o.write(function(){e.sandboxEl.style.height=t+"px"}).then(function(){return e._updateCachedDimensions()})}),t.override("matchWidthToContent",function(){var t,e=this;return o.read(function(){t=e.widgetEl?h(e.widgetEl).width:0}),o.write(function(){e.sandboxEl.style.width=t+"px"}).then(function(){return e._updateCachedDimensions()})}),t.after("initialize",function(){this._iframe=null,this._width=this._height=0,this._resizeHandlers=[]}),t.override("insert",function(t,e,n,r){var i=this,s=new p,a=this.targetGlobal.document,u=A(t,e,n,a);return o.write(y(r,null,u)),u.addEventListener("load",function(){(function(t){try{t.contentWindow.document}catch(t){return m.reject(t)}return m.resolve(t)})(u).then(null,y(R,null,t,e,n,u,a)).then(s.resolve,s.reject)},!1),u.addEventListener("error",s.reject,!1),s.promise.then(function(t){var e=d(i._didResize,S,i);return i._iframe=t,i.win.addEventListener("resize",e,!1),m.all([i._setTargetToBlank(),i.addRootClass(x),i.prependCss(T)])})}),t.override("onResize",function(t){this._resizeHandlers.push(t)}),t.after("styleSelf",function(){return this._updateCachedDimensions()})})},function(t,e){t.exports=function(){throw new Error("unimplemented method")}},function(t,e,n){var r=n(2),i=n(7),o=100,s=3e3;function a(t,e){this._inputsQueue=[],this._task=t,this._isPaused=!1,this._flushDelay=e&&e.flushDelay||o,this._pauseLength=e&&e.pauseLength||s,this._flushTimeout=void 0}a.prototype.add=function(t){var e=new r;return this._inputsQueue.push({input:t,taskDoneDeferred:e}),this._scheduleFlush(),e.promise},a.prototype._scheduleFlush=function(){this._isPaused||(clearTimeout(this._flushTimeout),this._flushTimeout=setTimeout(i(this._flush,this),this._flushDelay))},a.prototype._flush=function(){try{this._task.call(null,this._inputsQueue)}catch(t){this._inputsQueue.forEach(function(e){e.taskDoneDeferred.reject(t)})}this._inputsQueue=[],this._flushTimeout=void 0},a.prototype.pause=function(t){clearTimeout(this._flushTimeout),this._isPaused=!0,!t&&this._pauseLength&&setTimeout(i(this.resume,this),this._pauseLength)},a.prototype.resume=function(){this._isPaused=!1,this._scheduleFlush()},t.exports=a},function(t,e,n){var r,i=n(72),o=n(31),s=n(2),a=n(4),u=n(19),c=n(22),d=n(32),f=n(8),l=n(12),h=n(114),p=n(58),m=n(9),v=n(11),g=n(115),w=n(3),y=n(0),b=n(1),_=p(function(){return new s});function E(t){var e=t||{should_obtain_cookie_consent:!0,experiments:{}};return new g(e.should_obtain_cookie_consent,e.experiments)}t.exports={load:function(){var t,e,n,s;if(c.ie9()||c.ie10()||"http:"!==f.protocol&&"https:"!==f.protocol)return l.devError("Using default settings due to unsupported browser or protocol."),r=E(),void _().resolve();t={origin:f.origin},u.settings().indexOf("localhost")>-1&&(t.localSettings=!0),e=v.url(i.resourceBaseUrl+i.widgetIframeHtmlPath,t),n=function(t){var n,i,o,s;if(i=w.isTwitterURL(t.origin),o=e.substr(0,t.origin.length)===t.origin,s=w.isTwimgURL(t.origin),o&&i||s)try{(n="string"==typeof t.data?d.parse(t.data):t.data).namespace===h.settings&&(r=E(n.settings),_().resolve())}catch(t){l.devError(t)}},b.addEventListener("message",n),s=o({src:e,title:"Twitter settings iframe"},{display:"none"}),a.body.appendChild(s)},settingsLoaded:function(){var t,e,n;return t=new s,e=m.get("experimentOverride"),_().promise.then(function(){e&&e.name&&e.assignment&&((n={})[e.name]={bucket:e.assignment},r.experiments=y.aug(r.experiments,n)),t.resolve(r)}).catch(function(e){t.reject(e)}),t.promise}}},function(t,e){t.exports={settings:"twttr.settings"}},function(t,e){t.exports=function(t,e){this.shouldObtainCookieConsent=t,this.experiments=e||{}}},function(t,e){t.exports=function(t){return t.split("").map(function(t){return t.charCodeAt(0).toString(16)}).join("")}},function(t,e,n){t.exports=[n(118),n(123),n(131),n(133),n(135),n(149),n(155)]},function(t,e,n){var r=n(11),i=n(5),o=n(0),s=n(13),a=n(14)(),u=n(59),c="a.twitter-dm-button";t.exports=function(t){return a(t,c).map(function(t){return u(function(t){var e=t.getAttribute("data-show-screen-name"),n=s(t),a=t.getAttribute("href"),u=t.getAttribute("data-screen-name"),c=e?i.asBoolean(e):null,d=t.getAttribute("data-size"),f=r.decodeURL(a),l=f.recipient_id,h=t.getAttribute("data-text")||f.text,p=t.getAttribute("data-welcome-message-id")||f.welcomeMessageId;return o.aug(n,{screenName:u,showScreenName:c,size:d,text:h,userId:l,welcomeMessageId:p})}(t),t.parentNode,t)})}},function(t,e,n){var r=n(0);t.exports=function t(e){var n;if(e)return n=e.lang||e.getAttribute("data-lang"),r.isType("string",n)?n:t(e.parentElement)}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return n.e(2).then(function(r){var o;try{o=n(87),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(122),i=n(1),o=n(10),s=n(37),a=n(18),u=n(55),c=n(27),d=n(56),f=n(44),l=n(46),h=n(7),p=n(45),m=n(6),v=n(0),g=50,w={position:"absolute",visibility:"hidden",display:"block",transform:"rotate(0deg)"},y={position:"static",visibility:"visible"},b="twitter-widget",_="open",E="SandboxRoot",x=".SandboxRoot { display: none; max-height: 10000px; }";t.exports=c.couple(n(57),function(t){t.defineStatic("isSupported",function(){return!!i.HTMLElement.prototype.attachShadow&&f.inlineStyle()}),t.overrideProperty("id",{get:function(){return this.sandboxEl&&this.sandboxEl.id}}),t.overrideProperty("initialized",{get:function(){return!!this._shadowHost}}),t.overrideProperty("width",{get:function(){return this._width}}),t.overrideProperty("height",{get:function(){return this._height}}),t.overrideProperty("sandboxEl",{get:function(){return this._shadowHost}}),t.define("_updateCachedDimensions",function(){var t=this;return a.read(function(){var e,n=l(t.sandboxEl);"visible"==t.sandboxEl.style.visibility?t._width=n.width:(e=l(t.sandboxEl.parentElement).width,t._width=Math.min(n.width,e)),t._height=n.height})}),t.define("_didResize",function(){var t=this,e=this._resizeHandlers.slice(0);return this._updateCachedDimensions().then(function(){e.forEach(function(e){e(t)})})}),t.override("createElement",function(t){return this.targetGlobal.document.createElement(t)}),t.override("createFragment",function(){return this.targetGlobal.document.createDocumentFragment()}),t.override("htmlToElement",function(t){var e;return(e=this.createElement("div")).innerHTML=t,e.firstElementChild}),t.override("hasSelectedText",function(){return!!u.getSelectedText(this.targetGlobal)}),t.override("addRootClass",function(t){var e=this._shadowRootBody;return t=Array.isArray(t)?t:[t],this.initialized?a.write(function(){t.forEach(function(t){o.add(e,t)})}):m.reject(new Error("sandbox not initialized"))}),t.override("removeRootClass",function(t){var e=this._shadowRootBody;return t=Array.isArray(t)?t:[t],this.initialized?a.write(function(){t.forEach(function(t){o.remove(e,t)})}):m.reject(new Error("sandbox not initialized"))}),t.override("hasRootClass",function(t){return o.present(this._shadowRootBody,t)}),t.override("addStyleSheet",function(t,e){return this.addCss('@import url("'+t+'");',e).then(function(){return d(t)})}),t.override("prependStyleSheet",function(t){var e=this._shadowRoot;return this.addStyleSheet(t,function(t){var n=e.firstElementChild;return n?e.insertBefore(t,n):e.appendChild(t)})}),t.override("appendStyleSheet",function(t){var e=this._shadowRoot;return this.addStyleSheet(t,function(t){return e.appendChild(t)})}),t.override("addCss",function(t,e){var n;return this.initialized?f.inlineStyle()?((n=this.createElement("style")).type="text/css",n.appendChild(this.targetGlobal.document.createTextNode(t)),a.write(h(e,null,n))):m.resolve():m.reject(new Error("sandbox not initialized"))}),t.override("prependCss",function(t){var e=this._shadowRoot;return this.addCss(t,function(t){var n=e.firstElementChild;return n?e.insertBefore(t,n):e.appendChild(t)})}),t.override("appendCss",function(t){var e=this._shadowRoot;return this.addCss(t,function(t){return e.appendChild(t)})}),t.override("makeVisible",function(){return this.styleSelf(y)}),t.override("injectWidgetEl",function(t){var e=this;return this.initialized?this._shadowRootBody.firstElementChild?m.reject(new Error("widget already injected")):a.write(function(){e._shadowRootBody.appendChild(t)}).then(function(){return e._updateCachedDimensions()}).then(function(){var t=p(e._didResize,g,e);new r(e._shadowRootBody,t)}):m.reject(new Error("sandbox not initialized"))}),t.override("matchHeightToContent",function(){return m.resolve()}),t.override("matchWidthToContent",function(){return m.resolve()}),t.override("insert",function(t,e,n,r){var i=this.targetGlobal.document,o=this._shadowHost=i.createElement(b),u=this._shadowRoot=o.attachShadow({mode:_}),c=this._shadowRootBody=i.createElement("div");return v.forIn(e||{},function(t,e){o.setAttribute(t,e)}),o.id=t,u.appendChild(c),s.delegate(c,"click","A",function(t,e){e.hasAttribute("target")||e.setAttribute("target","_blank")}),m.all([this.styleSelf(w),this.addRootClass(E),this.prependCss(x),a.write(r.bind(null,o))])}),t.override("onResize",function(t){this._resizeHandlers.push(t)}),t.after("initialize",function(){this._shadowHost=this._shadowRoot=this._shadowRootBody=null,this._width=this._height=0,this._resizeHandlers=[]}),t.after("styleSelf",function(){return this._updateCachedDimensions()})})},function(t,e){var n;(n=function(t,e){function r(t,e){if(t.resizedAttached){if(t.resizedAttached)return void t.resizedAttached.add(e)}else t.resizedAttached=new function(){var t,e;this.q=[],this.add=function(t){this.q.push(t)},this.call=function(){for(t=0,e=this.q.length;t
    ',t.appendChild(t.resizeSensor),{fixed:1,absolute:1}[function(t,e){return t.currentStyle?t.currentStyle[e]:window.getComputedStyle?window.getComputedStyle(t,null).getPropertyValue(e):t.style[e]}(t,"position")]||(t.style.position="relative");var i,o,s=t.resizeSensor.childNodes[0],a=s.childNodes[0],u=t.resizeSensor.childNodes[1],c=(u.childNodes[0],function(){a.style.width=s.offsetWidth+10+"px",a.style.height=s.offsetHeight+10+"px",s.scrollLeft=s.scrollWidth,s.scrollTop=s.scrollHeight,u.scrollLeft=u.scrollWidth,u.scrollTop=u.scrollHeight,i=t.offsetWidth,o=t.offsetHeight});c();var d=function(t,e,n){t.attachEvent?t.attachEvent("on"+e,n):t.addEventListener(e,n)},f=function(){t.offsetWidth==i&&t.offsetHeight==o||t.resizedAttached&&t.resizedAttached.call(),c()};d(s,"scroll",f),d(u,"scroll",f)}var i=Object.prototype.toString.call(t),o="[object Array]"===i||"[object NodeList]"===i||"[object HTMLCollection]"===i||"undefined"!=typeof jQuery&&t instanceof jQuery||"undefined"!=typeof Elements&&t instanceof Elements;if(o)for(var s=0,a=t.length;s0;return this.updateCachedDimensions().then(function(){e&&t._resizeHandlers.forEach(function(e){e(t)})})}),t.define("loadDocument",function(t){var e=new a;return this.initialized?this.iframeEl.src?u.reject(new Error("widget already loaded")):(this.iframeEl.addEventListener("load",e.resolve,!1),this.iframeEl.addEventListener("error",e.reject,!1),this.iframeEl.src=t,e.promise):u.reject(new Error("sandbox not initialized"))}),t.after("initialize",function(){var t=new a,e=new a;this._iframe=null,this._iframeVersion=null,this._width=this._height=0,this._resizeHandlers=[],this._rendered=t,this._results=e,this._waitToSwapUntilRendered=!1}),t.override("insert",function(t,e,n,i){var a=this;return e=d.aug({id:t},f,e),n=d.aug({},l,n),this._iframe=s(e,n),p[t]=this,a._waitToSwapUntilRendered||this.onResize(o(function(){a.makeVisible()})),r.write(c(i,null,this._iframe))}),t.override("onResize",function(t){this._resizeHandlers.push(t)}),t.after("styleSelf",function(){return this.updateCachedDimensions()})}},function(t,e,n){var r=n(1),i=n(127),o=n(129),s=n(25),a=n(5),u=n(130);t.exports=function(t,e,n,c,d){function f(t){var e=u(this);s.trigger(t.type,{target:e,region:t.region,type:t.type,data:t.data||{}})}function l(e){var n=u(this),r=n&&n.id,i=a.asInt(e.width),o=a.asInt(e.height);r&&void 0!==i&&void 0!==o&&t(r,i,o)}(new i).attachReceiver(new o.Receiver(r,"twttr.button")).bind("twttr.private.trigger",f).bind("twttr.private.resizeButton",l),(new i).attachReceiver(new o.Receiver(r,"twttr.embed")).bind("twttr.private.initialized",function(t){var e=u(this),n=e&&e.id,r=t.iframe_version;n&&r&&c&&c(n,r)}).bind("twttr.private.trigger",f).bind("twttr.private.results",function(){var t=u(this),n=t&&t.id;n&&e&&e(n)}).bind("twttr.private.rendered",function(){var t=u(this),e=t&&t.id;e&&n&&n(e)}).bind("twttr.private.no_results",function(){var t=u(this),e=t&&t.id;e&&d&&d(e)}).bind("twttr.private.resize",l)}},function(t,e,n){var r=n(32),i=n(128),o=n(0),s=n(6),a=n(23),u="2.0";function c(t){this.registry=t||{}}function d(t){var e,n;return e=o.isType("string",t),n=o.isType("number",t),e||n||null===t}function f(t,e){return{jsonrpc:u,id:d(t)?t:null,error:e}}c.prototype._invoke=function(t,e){var n,r,i;n=this.registry[t.method],r=t.params||[],r=o.isType("array",r)?r:[r];try{i=n.apply(e.source||null,r)}catch(t){i=s.reject(t.message)}return a.isPromise(i)?i:s.resolve(i)},c.prototype._processRequest=function(t,e){var n,r;return function(t){var e,n,r;return!!o.isObject(t)&&(e=t.jsonrpc===u,n=o.isType("string",t.method),r=!("id"in t)||d(t.id),e&&n&&r)}(t)?(n="params"in t&&(r=t.params,!o.isObject(r)||o.isType("function",r))?s.resolve(f(t.id,i.INVALID_PARAMS)):this.registry[t.method]?this._invoke(t,{source:e}).then(function(e){return n=t.id,{jsonrpc:u,id:n,result:e};var n},function(){return f(t.id,i.INTERNAL_ERROR)}):s.resolve(f(t.id,i.METHOD_NOT_FOUND)),null!=t.id?n:s.resolve()):s.resolve(f(t.id,i.INVALID_REQUEST))},c.prototype.attachReceiver=function(t){return t.attachTo(this),this},c.prototype.bind=function(t,e){return this.registry[t]=e,this},c.prototype.receive=function(t,e){var n,a,u,c=this;try{u=t,t=o.isType("string",u)?r.parse(u):u}catch(t){return s.resolve(f(null,i.PARSE_ERROR))}return e=e||null,a=((n=o.isType("array",t))?t:[t]).map(function(t){return c._processRequest(t,e)}),n?function(t){return s.all(t).then(function(t){return(t=t.filter(function(t){return void 0!==t})).length?t:void 0})}(a):a[0]},t.exports=c},function(t){t.exports={PARSE_ERROR:{code:-32700,message:"Parse error"},INVALID_REQUEST:{code:-32600,message:"Invalid Request"},INVALID_PARAMS:{code:-32602,message:"Invalid params"},METHOD_NOT_FOUND:{code:-32601,message:"Method not found"},INTERNAL_ERROR:{code:-32603,message:"Internal error"}}},function(t,e,n){var r=n(8),i=n(1),o=n(32),s=n(2),a=n(22),u=n(0),c=n(3),d=n(7),f=a.ie9();function l(t,e,n){var r;t&&t.postMessage&&(f?r=(n||"")+o.stringify(e):n?(r={})[n]=e:r=e,t.postMessage(r,"*"))}function h(t){return u.isType("string",t)?t:"JSONRPC"}function p(t,e){return e?u.isType("string",t)&&0===t.indexOf(e)?t.substring(e.length):t&&t[e]?t[e]:void 0:t}function m(t,e){var n=t.document;this.filter=h(e),this.server=null,this.isTwitterFrame=c.isTwitterURL(n.location.href),t.addEventListener("message",d(this._onMessage,this),!1)}function v(t,e){this.pending={},this.target=t,this.isTwitterHost=c.isTwitterURL(r.href),this.filter=h(e),i.addEventListener("message",d(this._onMessage,this),!1)}u.aug(m.prototype,{_onMessage:function(t){var e,n=this;this.server&&(this.isTwitterFrame&&!c.isTwitterURL(t.origin)||(e=p(t.data,this.filter))&&this.server.receive(e,t.source).then(function(e){e&&l(t.source,e,n.filter)}))},attachTo:function(t){this.server=t},detach:function(){this.server=null}}),u.aug(v.prototype,{_processResponse:function(t){var e=this.pending[t.id];e&&(e.resolve(t),delete this.pending[t.id])},_onMessage:function(t){var e;if((!this.isTwitterHost||c.isTwitterURL(t.origin))&&(e=p(t.data,this.filter))){if(u.isType("string",e))try{e=o.parse(e)}catch(t){return}(e=u.isType("array",e)?e:[e]).forEach(d(this._processResponse,this))}},send:function(t){var e=new s;return t.id?this.pending[t.id]=e:e.resolve(),l(this.target,t,this.filter),e.promise}}),t.exports={Receiver:m,Dispatcher:v,_stringifyPayload:function(t){return arguments.length>0&&(f=!!t),f}}},function(t,e,n){var r=n(4);t.exports=function(t){for(var e,n=r.getElementsByTagName("iframe"),i=0;n[i];i++)if((e=n[i]).contentWindow===t)return e}},function(t,e,n){var r=n(5),i=n(0),o=n(3),s=n(13),a=n(14)(),u=n(63),c="a.twitter-moment";t.exports=function(t){return a(t,c).map(function(t){return u(function(t){var e=s(t),n={momentId:o.momentId(t.href),chrome:t.getAttribute("data-chrome"),limit:t.getAttribute("data-limit")};return i.forIn(n,function(t,n){var i=e[t];e[t]=r.hasValue(i)?i:n}),e}(t),t.parentNode,t)})}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return Promise.all([n.e(0),n.e(4)]).then(function(r){var o;try{o=n(89),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(0),i=n(13),o=n(14)(),s=n(64),a="a.periscope-on-air",u=/^https?:\/\/(?:www\.)?(?:periscope|pscp)\.tv\/@?([a-zA-Z0-9_]+)\/?$/i;t.exports=function(t){return o(t,a).map(function(t){return s(function(t){var e=i(t),n=t.getAttribute("href"),o=t.getAttribute("data-size"),s=u.exec(n)[1];return r.aug(e,{username:s,size:o})}(t),t.parentNode,t)})}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return n.e(5).then(function(r){var o;try{o=n(90),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(5),i=n(0),o=n(65),s=n(13),a=n(14)(),u=n(66),c=n(3),d=n(12),f="a.twitter-timeline,div.twitter-timeline,a.twitter-grid",l="Embedded Search timelines have been deprecated. See https://twittercommunity.com/t/deprecating-widget-settings/102295.",h="You may have been affected by an update to settings in embedded timelines. See https://twittercommunity.com/t/deprecating-widget-settings/102295.",p="Embedded grids have been deprecated and will now render as timelines. Please update your embed code to use the twitter-timeline class. More info: https://twittercommunity.com/t/update-on-the-embedded-grid-display-type/119564.";t.exports=function(t){return a(t,f).map(function(t){return u(function(t){var e=s(t),n=t.getAttribute("data-show-replies"),a={isPreconfigured:!!t.getAttribute("data-widget-id"),chrome:t.getAttribute("data-chrome"),tweetLimit:t.getAttribute("data-tweet-limit")||t.getAttribute("data-limit"),ariaLive:t.getAttribute("data-aria-polite"),theme:t.getAttribute("data-theme"),borderColor:t.getAttribute("data-border-color"),showReplies:n?r.asBoolean(n):null,profileScreenName:t.getAttribute("data-screen-name"),profileUserId:t.getAttribute("data-user-id"),favoritesScreenName:t.getAttribute("data-favorites-screen-name"),favoritesUserId:t.getAttribute("data-favorites-user-id"),likesScreenName:t.getAttribute("data-likes-screen-name"),likesUserId:t.getAttribute("data-likes-user-id"),listOwnerScreenName:t.getAttribute("data-list-owner-screen-name"),listOwnerUserId:t.getAttribute("data-list-owner-id"),listId:t.getAttribute("data-list-id"),listSlug:t.getAttribute("data-list-slug"),customTimelineId:t.getAttribute("data-custom-timeline-id"),staticContent:t.getAttribute("data-static-content"),url:t.href};return a.isPreconfigured&&(c.isSearchUrl(a.url)?d.publicError(l,t):d.publicLog(h,t)),"twitter-grid"===t.className&&d.publicLog(p,t),(a=i.aug(a,e)).dataSource=o(a),a.id=a.dataSource&&a.dataSource.id,a}(t),t.parentNode,t)})}},function(t,e,n){var r=n(28);t.exports=r.build([n(29),n(139)])},function(t,e,n){var r=n(0),i=n(138);t.exports=function(t){return"en"===t||r.contains(i,t)}},function(t,e){t.exports=["hi","zh-cn","fr","zh-tw","msa","fil","fi","sv","pl","ja","ko","de","it","pt","es","ru","id","tr","da","no","nl","hu","fa","ar","ur","he","th","cs","uk","vi","ro","bn","el","en-gb","gu","kn","mr","ta","bg","ca","hr","sr","sk"]},function(t,e,n){var r=n(3),i=n(0),o=n(19),s="collection:";function a(t,e){return r.collectionId(t)||e}t.exports=function(t){t.params({id:{},url:{}}),t.overrideProperty("id",{get:function(){var t=a(this.params.url,this.params.id);return s+t}}),t.overrideProperty("endpoint",{get:function(){return o.timeline(["collection"])}}),t.around("queryParams",function(t){return i.aug(t(),{collection_id:a(this.params.url,this.params.id)})}),t.before("initialize",function(){if(!a(this.params.url,this.params.id))throw new Error("one of url or id is required")})}},function(t,e,n){var r=n(28);t.exports=r.build([n(29),n(141)])},function(t,e,n){var r=n(3),i=n(0),o=n(19),s="event:";function a(t,e){return r.eventId(t)||e}t.exports=function(t){t.params({id:{},url:{}}),t.overrideProperty("id",{get:function(){var t=a(this.params.url,this.params.id);return s+t}}),t.overrideProperty("endpoint",{get:function(){return o.timeline(["event"])}}),t.around("queryParams",function(t){return i.aug(t(),{event_id:a(this.params.url,this.params.id)})}),t.before("initialize",function(){if(!a(this.params.url,this.params.id))throw new Error("one of url or id is required")})}},function(t,e,n){var r=n(28);t.exports=r.build([n(29),n(143)])},function(t,e,n){var r=n(3),i=n(0),o=n(19),s="likes:";function a(t){return r.likesScreenName(t.url)||t.screenName}t.exports=function(t){t.params({screenName:{},userId:{},url:{}}),t.overrideProperty("id",{get:function(){var t=a(this.params)||this.params.userId;return s+t}}),t.overrideProperty("endpoint",{get:function(){return o.timeline(["likes"])}}),t.define("_getLikesQueryParam",function(){var t=a(this.params);return t?{screen_name:t}:{user_id:this.params.userId}}),t.around("queryParams",function(t){return i.aug(t(),this._getLikesQueryParam())}),t.before("initialize",function(){if(!a(this.params)&&!this.params.userId)throw new Error("screen name or user id is required")})}},function(t,e,n){var r=n(28);t.exports=r.build([n(29),n(145)])},function(t,e,n){var r=n(3),i=n(0),o=n(19),s="list:";function a(t){var e=r.listScreenNameAndSlug(t.url)||t;return i.compact({screen_name:e.ownerScreenName,user_id:e.ownerUserId,list_slug:e.slug})}t.exports=function(t){t.params({id:{},ownerScreenName:{},ownerUserId:{},slug:{},url:{}}),t.overrideProperty("id",{get:function(){var t,e,n;return this.params.id?s+this.params.id:(e=(t=a(this.params))&&t.list_slug.replace(/-/g,"_"),n=t&&(t.screen_name||t.user_id),s+(n+":")+e)}}),t.overrideProperty("endpoint",{get:function(){return o.timeline(["list"])}}),t.define("_getListQueryParam",function(){return this.params.id?{list_id:this.params.id}:a(this.params)}),t.around("queryParams",function(t){return i.aug(t(),this._getListQueryParam())}),t.before("initialize",function(){var t=a(this.params);if(i.isEmptyObject(t)&&!this.params.id)throw new Error("qualified slug or list id required")})}},function(t,e,n){var r=n(28);t.exports=r.build([n(29),n(147)])},function(t,e,n){var r=n(3),i=n(5),o=n(0),s=n(19),a="profile:";function u(t,e){return r.screenName(t)||e}t.exports=function(t){t.params({showReplies:{fallback:!1,transform:i.asBoolean},screenName:{},userId:{},url:{}}),t.overrideProperty("id",{get:function(){var t=u(this.params.url,this.params.screenName);return a+(t||this.params.userId)}}),t.overrideProperty("endpoint",{get:function(){return s.timeline(["profile"])}}),t.define("_getProfileQueryParam",function(){var t=u(this.params.url,this.params.screenName),e=t?{screen_name:t}:{user_id:this.params.userId};return o.aug(e,{with_replies:this.params.showReplies?"true":"false"})}),t.around("queryParams",function(t){return o.aug(t(),this._getProfileQueryParam())}),t.before("initialize",function(){if(!u(this.params.url,this.params.screenName)&&!this.params.userId)throw new Error("screen name or user id is required")})}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return Promise.all([n.e(0),n.e(6)]).then(function(r){var o;try{o=n(91),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(10),i=n(3),o=n(0),s=n(13),a=n(14)(),u=n(67),c="blockquote.twitter-tweet, blockquote.twitter-video",d=/\btw-align-(left|right|center)\b/;t.exports=function(t,e){return a(t,c).map(function(t){return u(function(t){var e=s(t),n=t.getElementsByTagName("A"),a=n&&n[n.length-1],u=a&&i.status(a.href),c=t.getAttribute("data-conversation"),f="none"==c||"hidden"==c||r.present(t,"tw-hide-thread"),l=t.getAttribute("data-cards"),h="none"==l||"hidden"==l||r.present(t,"tw-hide-media"),p=t.getAttribute("data-align")||t.getAttribute("align"),m=t.getAttribute("data-theme");return!p&&d.test(t.className)&&(p=RegExp.$1),o.aug(e,{tweetId:u,hideThread:f,hideCard:h,align:p,theme:m,id:u})}(t),t.parentNode,t,e)})}},function(t,e,n){var r=n(35),i=n(151),o="tfw_horizon_tweet_embed_9555";t.exports={isHorizonTweetEnabled:function(t,e){return!function(t,e){return function(t){return!(!t||!t.partner||"applenews"!==t.partner)}(e)||i.some(function(e){return new RegExp(e,"i").test(t)})}(r.rootDocumentLocation(),e)&&!(!t||!t[o]||"hte"!==t[o].bucket)}}},function(t){t.exports=["^https?://www.redditmedia.com/.*"]},function(t,e,n){var r=n(85),i=n(21),o="tfw_horizon_tweet_embed_9555";t.exports=function(t,e){var n;t&&(n=t[o])&&n.bucket&&r(o,n.bucket,n.version,i.formatHorizonTweetData(e))}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return n.e(7).then(function(r){var o;try{o=n(92),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return Promise.all([n.e(0),n.e(8)]).then(function(r){var o;try{o=n(93),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(10),i=n(0),o=n(13),s=n(14)(),a=n(68),u=n(5),c="a.twitter-share-button, a.twitter-mention-button, a.twitter-hashtag-button",d="twitter-hashtag-button",f="twitter-mention-button";t.exports=function(t){return s(t,c).map(function(t){return a(function(t){var e=o(t),n={screenName:t.getAttribute("data-button-screen-name"),text:t.getAttribute("data-text"),type:t.getAttribute("data-type"),size:t.getAttribute("data-size"),url:t.getAttribute("data-url"),hashtags:t.getAttribute("data-hashtags"),via:t.getAttribute("data-via"),buttonHashtag:t.getAttribute("data-button-hashtag")};return i.forIn(n,function(t,n){var r=e[t];e[t]=u.hasValue(r)?r:n}),e.screenName=e.screenName||e.screen_name,e.buttonHashtag=e.buttonHashtag||e.button_hashtag||e.hashtag,r.present(t,d)&&(e.type="hashtag"),r.present(t,f)&&(e.type="mention"),e}(t),t.parentNode,t)})}},function(t,e,n){var r=n(2);t.exports=function(t,e){var i=new r;return n.e(3).then(function(r){var o;try{o=n(94),i.resolve(new o(t,e))}catch(t){i.reject(t)}}.bind(null,n)).catch(function(t){i.reject(t)}),i.promise}},function(t,e,n){var r=n(0);t.exports=r.aug({},n(158),n(159),n(160),n(161),n(162),n(163),n(164))},function(t,e,n){var r=n(59),i=n(17)(["userId"],{},r);t.exports={createDMButton:i}},function(t,e,n){var r=n(62),i=n(17)(["screenName"],{},r);t.exports={createFollowButton:i}},function(t,e,n){var r=n(63),i=n(17)(["momentId"],{},r);t.exports={createMoment:i}},function(t,e,n){var r=n(64),i=n(17)(["username"],{},r);t.exports={createPeriscopeOnAirButton:i}},function(t,e,n){var r=n(8),i=n(12),o=n(3),s=n(0),a=n(5),u=n(65),c=n(66),d=n(17)([],{},c),f=n(6),l="Embedded grids have been deprecated. Please use twttr.widgets.createTimeline instead. More info: https://twittercommunity.com/t/update-on-the-embedded-grid-display-type/119564.",h={createTimeline:p,createGridFromCollection:function(t){var e=s.toRealArray(arguments).slice(1),n={sourceType:"collection",id:t};return e.unshift(n),i.publicLog(l),p.apply(this,e)}};function p(t){var e,n=s.toRealArray(arguments).slice(1);return a.isString(t)||a.isNumber(t)?f.reject("Embedded timelines with widget settings have been deprecated. See https://twittercommunity.com/t/deprecating-widget-settings/102295."):s.isObject(t)?(t=t||{},n.forEach(function(t){s.isType("object",t)&&function(t){t.ariaLive=t.ariaPolite}(e=t)}),e||(e={},n.push(e)),t.lang=e.lang,t.tweetLimit=e.tweetLimit,t.showReplies=e.showReplies,e.dataSource=u(t),d.apply(this,n)):f.reject("data source must be an object.")}o.isTwitterURL(r.href)&&(h.createTimelinePreview=function(t,e,n){var r={previewParams:t,useLegacyDefaults:!0,isPreviewTimeline:!0};return r.dataSource=u(r),d(e,r,n)}),t.exports=h},function(t,e,n){var r,i=n(0),o=n(67),s=n(17),a=(r=s(["tweetId"],{},o),function(){return i.toRealArray(arguments).slice(1).forEach(function(t){i.isType("object",t)&&(t.hideCard="none"==t.cards||"hidden"==t.cards,t.hideThread="none"==t.conversation||"hidden"==t.conversation)}),r.apply(this,arguments)});t.exports={createTweet:a,createTweetEmbed:a,createVideo:a}},function(t,e,n){var r=n(0),i=n(68),o=n(17),s=o(["url"],{type:"share"},i),a=o(["buttonHashtag"],{type:"hashtag"},i),u=o(["screenName"],{type:"mention"},i);function c(t){return function(){return r.toRealArray(arguments).slice(1).forEach(function(t){r.isType("object",t)&&(t.screenName=t.screenName||t.screen_name,t.buttonHashtag=t.buttonHashtag||t.button_hashtag||t.hashtag)}),t.apply(this,arguments)}}t.exports={createShareButton:c(s),createHashtagButton:c(a),createMentionButton:c(u)}},function(t,e,n){var r,i,o,s=n(4),a=n(1),u=0,c=[],d=s.createElement("a");function f(){var t,e;for(u=1,t=0,e=c.length;t + + + + + + + + + + + + + + + + + + +June Choe: Embedding videos in {reactable} tables + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Embedding videos in {reactable} tables

    + + + +

    Pushing the limits of expandable row details

    +
    + + + +
    +
    + +
    +

    In a {reactable} table, you can have a row expand to reveal more details by supplying the details argument with a function returning an image, raw html, another reactable table, etc. There are many examples of this in the package vignette, and they give you a good sense of just how flexible and powerful this feature is.

    +

    My first reaction to this was that it seemed like just about anything that can be displayed on a web page can be embedded in the expandable details. So what about something very unusual like… videos? Can {reactable} handle it? Are there potential usecases of this?

    +

    Annotated #tidytuesday screencasts

    +

    While entertaining this idea, I remembered coming across a tweet by Alex Cookson with a link to a very detailed spreadsheet containing timestamped notes of David Robinson’s live #tidytuesday screencasts.

    + + +

    So I turned the spreadsheet into a {reactable} table with rows that can expand to reveal a Youtube video at the timestamp. I actually think this makes a really cool use case - it’s easier here than in Google Spreadsheet to navigate around the table with pagination and search bar, and you don’t need to constantly open and close Youtube videos in new windows (in fact, you can keep multiple videos open across rows here!).

    +

    Try it out for yourself!

    +
    +
    + +
    +

    Code

    +
    +
    +
    library(tidyverse)
    +library(htmltools)
    +library(reactable)
    +
    +# David Robinson's (@drob) #tidytuesday screencast annotations, made by Alex Cookson (@alexcookson)
    +screencasts <-
    +  gsheet::gsheet2tbl("docs.google.com/spreadsheets/d/1pjj_G9ncJZPGTYPkR1BYwzA6bhJoeTfY2fJeGKSbOKM") %>% 
    +  select(Screencast, Date, Timestamp = `Timestamp (sec)`, Link:Functions) %>% 
    +  mutate(Link = str_extract(Link, "(?<=v=).*(?=&)"))
    +
    +
    +###############
    +## The Table ##
    +###############
    +
    +reactable(screencasts,
    +  
    +  # Function to embed Youtube Video 
    +  details = function(index){
    +    
    +    # Grab video info from hidden columns
    +    link <- screencasts$Link[index]
    +    time <- screencasts$Timestamp[index]
    +    
    +    # Div container to add grey padding around the video
    +    tags$div(style = "text-align:center; padding:10px; background:grey",
    +             
    +             # The actual video
    +             tags$iframe(
    +               height = "640", width = "640", allow = "fullscreen",
    +               src = glue::glue("https://www.youtube.com/embed/{link}?start={time}&autoplay=1")
    +             )
    +             
    +    )
    +    
    +  },
    +  
    +  # Column options
    +  columns = list(
    +    Link = colDef(show = F),
    +    Timestamp = colDef(show = F),
    +    Description = colDef(width = 500)
    +  ),
    +  
    +  # Some theme options
    +  searchable = TRUE,
    +  bordered = TRUE,
    +  fullWidth = TRUE,
    +  theme = reactableTheme(
    +    style = list(fontSize = '14px'),
    +    searchInputStyle = list(width = "100%")
    +  ),
    +  
    +)
    +
    +
    +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-12-videos-in-reactable/preview.png b/docs/posts/2020-09-12-videos-in-reactable/preview.png new file mode 100644 index 00000000..018e5b7c Binary files /dev/null and b/docs/posts/2020-09-12-videos-in-reactable/preview.png differ diff --git a/docs/posts/2020-09-14-tidytuesday-2020-week-38/2020-09-14-tidytuesday-2020-week-38_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-14-tidytuesday-2020-week-38/2020-09-14-tidytuesday-2020-week-38_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-14-tidytuesday-2020-week-38/2020-09-14-tidytuesday-2020-week-38_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-14-tidytuesday-2020-week-38/index.html b/docs/posts/2020-09-14-tidytuesday-2020-week-38/index.html new file mode 100644 index 00000000..59bc69ec --- /dev/null +++ b/docs/posts/2020-09-14-tidytuesday-2020-week-38/index.html @@ -0,0 +1,2744 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 week 38 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 week 38

    + + + +

    Visualizing two decades of primary and secondary education spending with {gt}

    +
    + + + +
    + +
    + +
    +

    Visualization

    +

    I had difficulty embedding an HTML table without overriding its styles so the table is also available on its own here.

    +
    +

    +
    +

    Things I learned

    +
      +
    • Basics of working with tables and {gt}1

    • +
    • Putting different font styles together in a nice way

    • +
    +

    Things to improve

    +
      +
    • Summarize the data a bit more so the table isn’t huge

    • +
    • Add conditional formatting (learn how tab_style() and tab_options() work)

    • +
    • Figure out how to save {gt} tables into pdf or png

    • +
    • Figure out how to include an html table without overriding css styles

    • +
    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +library(gt)
    +
    +kids <- tidytuesdayR::tt_load("2020-09-15")$kids
    +
    +
    +# TABLE DATA
    +
    +state_regions <- setNames(c(as.character(state.region), "Northeast"), c(state.name, "District of Columbia"))
    +
    +kids_tbl_data <- kids %>% 
    +  filter(variable == "PK12ed") %>%
    +  mutate(region = state_regions[state]) %>% 
    +  select(region, state, year, inf_adj_perchild) %>% 
    +  pivot_wider(names_from = year, values_from = inf_adj_perchild) %>%
    +  mutate(Trend = NA) 
    +
    +
    +# SPARKLINE
    +
    +plotter <- function(data){
    +  data %>% 
    +    tibble(
    +      year = 1997:2016,
    +      value = data
    +    ) %>% 
    +    ggplot(aes(year, value)) +
    +    geom_line(size = 10, show.legend = FALSE) +
    +    theme_void() +
    +    scale_y_continuous(expand = c(0, 0))
    +}
    +
    +spark_plots <- kids_tbl_data %>% 
    +  group_split(state) %>% 
    +  map(~ flatten_dbl(select(.x, where(is.numeric)))) %>% 
    +  map(plotter)
    +
    +
    +# TABLE
    +
    +kids_tbl <- kids_tbl_data %>% 
    +  gt(
    +    groupname_col = 'region',
    +    rowname_col = 'state'
    +  ) %>% 
    +  fmt_number(
    +    columns = 3:22
    +  ) %>% 
    +  summary_rows(
    +    groups = TRUE,
    +    columns = 3:22,
    +    fns = list(Average = ~mean(.))
    +  ) %>% 
    +  text_transform(
    +    locations = cells_body(vars(Trend)),
    +    fn = function(x){
    +      map(spark_plots, ggplot_image, height = px(15), aspect_ratio = 4)
    +    }
    +  ) %>%
    +  tab_header(
    +    title = md("**State-by-State Spending on Primary and Secondary Education over 20 years**"),
    +    subtitle = md("*$1000s per child adjusted for inflation*")
    +  ) %>% 
    +  tab_source_note(
    +    md("**By**: @yjunechoe<br>
    +        **Inspiration**: @thomas_mock<br>
    +        **Data**: Urban Institute | {tidykids} by Joshua Rosenberg")
    +  ) %>% 
    +  tab_style(
    +    style = list(
    +      cell_text(font = "Futura MdCn BT")
    +    ),
    +    locations = list(
    +      cells_title(groups = "title")
    +    )
    +  ) %>%
    +  tab_options(
    +    table.width = 50,
    +    heading.align = "left",
    +    heading.title.font.size = 72,
    +    heading.subtitle.font.size = 32,
    +    row_group.font.size = 42,
    +    row_group.font.weight = 'bold',
    +    row_group.border.top.color = "black",
    +    row_group.border.bottom.color = "black",
    +    table.border.top.color = "black",
    +    heading.border.bottom.color = "white",
    +    heading.border.bottom.width = px(10),
    +    table.font.names = "Roboto",
    +    column_labels.font.size = 20,
    +    column_labels.border.bottom.color = "black",
    +    column_labels.border.bottom.width= px(3),
    +    summary_row.border.color = "black", 
    +    summary_row.background.color = "#c0c5ce",
    +    table.border.bottom.color = "black"
    +  )
    +
    +
    +
    +
    +
    +
    +
      +
    1. Many thanks to Thomas Mock’s blog posts on {gt} (1) (2), a well as to the developers of {gt} for what I think is one of the most comprehensive vignette I’ve ever seen for a package!↩︎

    2. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-14-tidytuesday-2020-week-38/preview.png b/docs/posts/2020-09-14-tidytuesday-2020-week-38/preview.png new file mode 100644 index 00000000..b2d8bc20 Binary files /dev/null and b/docs/posts/2020-09-14-tidytuesday-2020-week-38/preview.png differ diff --git a/docs/posts/2020-09-14-tidytuesday-2020-week-38/tidytuesday_2020_38_table.html b/docs/posts/2020-09-14-tidytuesday-2020-week-38/tidytuesday_2020_38_table.html new file mode 100644 index 00000000..309d7974 --- /dev/null +++ b/docs/posts/2020-09-14-tidytuesday-2020-week-38/tidytuesday_2020_38_table.html @@ -0,0 +1,1726 @@ + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    State-by-State Spending on Primary and Secondary Education over 20 years
    $1000s per child adjusted for inflation
    19971998199920002001200220032004200520062007200820092010201120122013201420152016Trend
    South
    Alabama3.934.164.434.604.654.744.834.885.065.415.836.216.116.035.985.655.745.785.765.67
    Arkansas3.894.144.294.404.544.714.915.055.515.645.745.786.206.556.625.975.895.905.915.93
    Delaware5.635.745.806.046.246.486.746.957.177.467.127.457.257.357.588.148.068.158.238.44
    Florida4.454.564.754.684.764.865.075.215.385.565.916.075.855.795.845.415.385.525.545.50
    Georgia4.614.805.095.255.505.775.855.895.826.016.276.586.496.356.156.065.925.956.086.25
    Kentucky4.044.024.224.314.424.564.634.705.095.335.325.635.595.795.895.935.835.735.815.88
    Louisiana3.984.214.414.474.664.875.055.205.325.615.866.366.666.696.697.016.186.186.276.22
    Maryland5.075.105.345.435.756.106.206.276.446.777.307.788.068.168.067.918.048.088.207.33
    Mississippi3.413.593.724.034.074.144.424.644.775.055.045.195.255.275.085.175.155.155.265.35
    North Carolina4.224.414.604.894.914.995.015.015.205.195.405.345.695.515.265.165.175.075.205.19
    Oklahoma4.174.374.584.735.015.295.175.035.275.335.535.605.655.725.055.035.075.044.964.90
    South Carolina4.194.414.684.985.255.565.615.625.765.896.046.366.396.215.995.946.026.236.296.38
    Tennessee3.853.984.134.434.474.554.644.724.824.804.865.105.315.415.535.315.235.345.285.23
    Texas4.344.544.695.025.165.315.455.555.455.455.545.785.836.005.825.445.405.505.605.63
    Virginia4.985.335.435.956.106.306.366.366.697.007.297.517.527.467.247.187.237.337.427.28
    West Virginia5.575.686.076.346.416.486.576.616.676.776.806.837.257.987.947.587.327.247.297.25
    Average4.404.564.764.975.125.295.415.485.655.835.996.226.326.396.306.186.106.146.196.15
    West
    Alaska7.557.137.627.737.958.208.388.488.809.069.4710.9811.6911.9711.9411.2611.6311.5012.1110.63
    Arizona3.713.723.813.944.004.074.274.414.434.514.614.804.864.734.494.334.084.234.154.15
    California4.284.654.855.125.566.036.116.176.216.306.646.826.666.386.166.196.126.246.767.17
    Colorado4.384.644.764.845.015.265.415.565.635.745.656.085.845.915.755.575.595.775.876.06
    Hawaii3.233.453.874.184.855.525.956.266.216.517.047.197.436.385.825.485.375.985.545.72
    Idaho3.994.104.304.254.474.714.674.594.564.494.464.524.604.524.254.114.204.134.144.20
    Montana4.925.035.115.205.365.555.735.885.875.986.166.296.426.696.666.486.476.626.576.67
    Nevada4.234.334.494.524.604.694.794.804.925.175.465.555.575.625.675.375.395.375.425.54
    New Mexico3.964.164.474.664.905.135.375.545.595.765.926.086.206.145.855.635.645.596.035.86
    Oregon5.085.385.555.605.785.995.855.715.936.046.186.486.586.416.356.246.186.376.646.84
    Utah3.413.523.673.693.823.963.933.873.863.833.834.104.183.773.973.944.073.983.944.07
    Washington4.905.105.165.285.375.505.575.575.635.645.806.166.406.246.186.226.156.426.737.18
    Wyoming5.815.926.406.687.047.357.537.627.838.429.369.489.7310.1610.4610.4510.2510.2310.3310.59
    Average4.574.704.935.055.295.545.665.735.815.966.206.506.636.536.436.256.246.346.486.51
    Northeast
    Connecticut6.706.397.077.267.507.828.038.248.368.678.959.289.8910.069.789.869.9710.2910.5610.81
    District of Columbia6.117.197.739.009.7910.7111.4512.0712.6912.8412.5116.3117.3518.8117.6417.8917.2816.9817.1017.66
    Maine5.926.276.146.396.546.747.007.247.357.537.717.888.268.338.338.117.928.098.388.45
    Massachusetts5.525.956.296.606.927.317.467.617.797.948.118.468.918.748.638.898.989.349.519.49
    New Hampshire5.065.225.365.665.936.256.606.937.157.387.648.098.468.819.019.159.229.409.639.82
    New Jersey7.227.617.718.278.338.459.059.609.9410.2510.3810.6510.8711.3010.7510.9111.3011.7211.5211.59
    New York7.057.377.698.178.468.839.199.529.8310.2210.5811.0611.5011.7711.8411.8612.5912.8913.3012.77
    Pennsylvania5.265.946.176.216.025.886.567.177.387.467.547.717.868.138.067.968.638.568.839.13
    Rhode Island6.066.336.476.677.047.457.888.308.398.579.099.309.489.579.569.599.809.799.9610.20
    Vermont5.636.216.747.207.187.258.048.779.139.319.6510.0210.5610.9310.8811.0311.2911.4611.7212.03
    Average6.056.456.747.147.377.678.138.558.809.029.229.8810.3110.6510.4510.5210.7010.8511.0511.20
    North Central
    Illinois4.444.905.225.425.495.625.906.146.216.366.466.687.127.327.287.287.327.557.667.73
    Indiana4.554.804.914.975.105.275.505.685.945.755.765.505.615.725.465.405.235.155.165.20
    Iowa4.625.105.225.365.345.355.635.875.936.026.126.346.596.626.616.676.796.917.057.14
    Kansas4.734.834.885.015.215.445.505.545.525.745.996.246.336.096.005.935.996.036.066.01
    Michigan5.666.036.256.446.386.386.877.327.306.647.327.027.127.176.906.686.516.466.576.59
    Minnesota5.575.525.836.045.996.016.166.266.336.426.526.687.236.886.766.716.816.927.157.34
    Missouri4.324.494.724.895.155.435.445.435.465.595.745.966.106.145.915.855.925.986.116.15
    Nebraska4.714.714.744.915.215.525.665.755.685.736.056.156.436.866.847.057.157.187.297.47
    North Dakota4.214.564.734.945.055.195.585.886.016.066.086.326.506.887.036.956.977.007.487.55
    Ohio4.765.055.295.515.705.946.286.596.606.656.626.736.877.027.047.116.836.927.077.33
    South Dakota3.994.074.264.444.604.804.914.985.045.045.035.185.265.355.295.065.035.165.215.30
    Wisconsin5.796.006.166.246.456.696.836.937.007.027.057.177.387.537.707.147.117.107.157.11
    Average4.785.005.185.355.475.645.856.036.086.096.236.336.546.636.576.496.476.536.666.74
    By: @yjunechoe
    +Inspiration: @thomas_mock
    +Data: Urban Institute | {tidykids} by Joshua Rosenberg
    + + + \ No newline at end of file diff --git a/docs/posts/2020-09-20-plot-makeover-1/biblio.bib b/docs/posts/2020-09-20-plot-makeover-1/biblio.bib new file mode 100644 index 00000000..aae7aaed --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/biblio.bib @@ -0,0 +1,7 @@ +@proceedings{HusbandEtAl2020AMLaP, + author = {E. Matthew Husband and Nikole Patson}, + title = {Priming of implicatures within and between categories: The case of or}, + year = {2020}, + organization = {AMLaP2020}, + url = {https://amlap2020.github.io/a/272.pdf} +} \ No newline at end of file diff --git a/docs/posts/2020-09-20-plot-makeover-1/index.html b/docs/posts/2020-09-20-plot-makeover-1/index.html new file mode 100644 index 00000000..9db1e72a --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/index.html @@ -0,0 +1,2865 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Plot Makeover #1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Plot Makeover #1

    + + + +

    Flattening a faceted grid for strictly horizontal comparisons

    +
    + + + +
    +
    + +
    +
    + +
    +
    + +
    +

    This is the first installment of plot makeover where I take a plot in the wild and make very opinionated modifications to it.

    +

    Before

    +

    Our plot-in-the-wild comes from the recent AMLAP 2020 conference, where I presented my thesis research and had the opportunity to talk with and listen to expert psycholinguists around the world. The plot that I’ll be looking at here is Figure 3 from the abstract of a work by E. Matthew Husband and Nikole Patson (Husband and Patson 2020).

    +
    +
    +Plot from Husband and Patson (2020) +

    +Figure 1: Plot from Husband and Patson (2020) +

    +
    +
    +

    What we have is 6 pairs of barplots with error bars, laid out in a 2-by-3 grid. The total of 12 bars are grouped at three levels which are mapped in the following way:

    +
      +
    • First level is mapped to the grid column.

    • +
    • Second level is mapped to the grid row.

    • +
    • Third level is mapped to the x-axis.

    • +
    +

    To get a better sense of what they did, and to make data for the plot makeover, I have recreated the original plot below:1

    +

    1. Data

    +
    +
    +
    library(tidyverse)
    +df <- crossing(level_1 = fct_inorder(c("Within", "Between")),
    +               level_2 = fct_inorder(c("Some", "Number", "Or")),
    +               level_3 = factor(c("Strong", "Weak")))
    +df$barheight <- c(.63, .35, .72, .55, .61, .15, .60, .55, .52, .63, .17, .16)
    +
    +df
    +
    +
    +
    + +
    +
      # A tibble: 12 x 4
    +     level_1 level_2 level_3 barheight
    +     <fct>   <fct>   <fct>       <dbl>
    +   1 Within  Some    Strong       0.63
    +   2 Within  Some    Weak         0.35
    +   3 Within  Number  Strong       0.72
    +   4 Within  Number  Weak         0.55
    +   5 Within  Or      Strong       0.61
    +   6 Within  Or      Weak         0.15
    +   7 Between Some    Strong       0.6 
    +   8 Between Some    Weak         0.55
    +   9 Between Number  Strong       0.52
    +  10 Between Number  Weak         0.63
    +  11 Between Or      Strong       0.17
    +  12 Between Or      Weak         0.16
    +
    +

    2. Plot

    +
    +
    +
    df %>% 
    +  ggplot(aes(level_3, barheight)) +
    +  geom_col(
    +    aes(fill = level_3),
    +    show.legend = FALSE
    +  ) +
    +  geom_errorbar(
    +    aes(ymin = barheight - .05, ymax = barheight + .05),
    +    width = .1) +
    +  facet_grid(level_2 ~ level_1) +
    +  theme_bw() +
    +  scale_fill_manual(values = c('grey40', 'grey80')) +
    +  ylim(0, 1) +
    +  labs(
    +    y = "Proportion of Strong Responses",
    +    x = "Prime Type") +
    +  theme_bw()
    +
    +
    +

    +
    + +

    My Plan

    +

    Major Changes:

    +
      +
    • Flatten the grid in some way so that everything is laid out left-to-right and you can make comparisons horizontally.

    • +
    • Cap the y axis to make it clear that the values (proportions) can only lie between 0 and 1.

    • +
    +

    Minor Changes:

    +
      +
    • Remove grid lines

    • +
    • Increase space between axis and axis titles.

    • +
    • Remove boxes around strip labels

    • +
    • Make strip (facet) labels larger and more readable.

    • +
    • Increase letter spacing (probably by changing font)

    • +
    +

    After

    +

    I actually couldn’t settle on one final product2 so here are two plots that incorporate the changes that I wanted to make. I think that both look nice and you may prefer one style over the other depending on what relationships/comparisons you want your graph to emphasize.

    +

    Point-line plot

    +

    I got a suggestion that the groups could additionally be mapped to shape for greater clarity, so I’ve incorporated that change.3

    +
    +

    +
    +
    +
    +
    dodge <- position_dodge(width = .5)
    +
    +df %>% 
    +  mutate(level_3 = as.numeric(level_3)) %>% 
    +  ggplot(aes(x = level_3, y = barheight, group = level_1)) +
    +  geom_errorbar(
    +    aes(ymin = barheight - .05, ymax = barheight + .05),
    +    width = .2,
    +    position = dodge
    +  ) +
    +  geom_line(
    +    aes(linetype = level_1),
    +    position = dodge,
    +    show.legend = FALSE
    +  ) +
    +  geom_point(
    +    aes(shape = level_1, fill = level_1),
    +    size = 1.5,
    +    stroke = .6,
    +    position = dodge
    +  ) + 
    +  scale_fill_manual(values = c("black", "white")) +
    +  scale_shape_manual(values = c(21, 24)) +
    +  facet_wrap(~ level_2) +
    +  scale_x_continuous(
    +    breaks = 1:2,
    +    labels = levels(df$level_3),
    +    expand = expansion(.2),
    +  ) +
    +  scale_y_continuous(
    +    limits = c(0, 1),
    +    expand = expansion(c(0, .1))
    +  ) +
    +  lemon::coord_capped_cart(left = "both") +
    +  guides(
    +    fill = guide_none(),
    +    shape = guide_legend(
    +      title = NULL,
    +      direction = "horizontal",
    +      label.theme = element_text(size = 10, family = "Montserrat"),
    +      override.aes = list(fill = c("black", "white"))
    +    )
    +  ) +
    +  labs(
    +    y = "Strong Responses",
    +    x = "Prime Type",
    +    linetype = "Category"
    +  ) +
    +  ggthemes::theme_clean(base_size = 14) +
    +  theme(
    +    text = element_text(family = "Montserrat"),
    +    legend.position = c(.18, .87),
    +    legend.background = element_rect(color = NA, fill = NA),
    +    strip.text = element_text(size = 13),
    +    plot.margin = margin(5, 5, 5, 5, 'mm'),
    +    axis.title.x = element_text(vjust = -3),
    +    axis.title.y = element_text(vjust = 5),
    +    plot.background = element_blank(),
    +    panel.grid.major.y = element_blank()
    +  )
    +
    +
    +
    +

    Bar plot

    +
    +

    +
    +
    +
    +
    dodge <- position_dodge(width = .5)
    +
    +df %>% 
    +  mutate(level_3 = as.numeric(level_3)) %>% 
    +  ggplot(aes(x = level_3, y = barheight, group = level_1)) +
    +  geom_col(position = dodge, width = .5, color = 'white', aes(fill = level_1)) +
    +  scale_fill_manual(values = c("grey30", "grey60")) +
    +  geom_errorbar(
    +    aes(ymin = barheight - .05, ymax = barheight + .05),
    +    width = .2,
    +    position = dodge
    +  ) +
    +  facet_wrap(~ level_2) +
    +  scale_x_continuous(
    +    breaks = 1:2,
    +    labels = levels(df$level_3),
    +    expand = expansion(.2),
    +  ) +
    +  ylim(0, 1) +
    +  lemon::coord_capped_cart(left = "both") +
    +  labs(
    +    y = "Strong Responses",
    +    x = "Prime Type",
    +    fill = NULL
    +  ) +
    +  ggthemes::theme_clean(base_size=14) +
    +  theme(
    +    text = element_text(family = "Montserrat"),
    +    legend.text = element_text(size = 10),
    +    legend.key.size = unit(5, 'mm'),
    +    legend.direction = "horizontal",
    +    legend.position = c(.17, .85),
    +    legend.background = element_blank(),
    +    strip.text = element_text(size = 14),
    +    axis.ticks.x = element_blank(),
    +    axis.title.x = element_text(vjust = -3),
    +    axis.title.y = element_text(vjust = 5),
    +    panel.grid.major.y = element_blank(),
    +    plot.background = element_blank(),
    +    plot.margin = margin(5, 5, 5, 5, 'mm')
    +  )
    +
    +
    +
    + +
    +
    +
    +Husband, E. Matthew, and Nikole Patson. 2020. Priming of Implicatures Within and Between Categories: The Case of or. AMLaP2020. https://amlap2020.github.io/a/272.pdf. +
    +
    +
    +
    +
      +
    1. But note that this is likely not how the original plot was generated: the authors were likely feeding ggplot2 with the raw data (involving 1s and 0s in this case), but here I am just grabbing the summary statistic that was mapped to the bar aesthetic (hence my decision to name the y variable barheight).↩︎

    2. +
    3. I ran the first plot by a friend who has a degree in design, and she recommended several changes that eventually ended up being the second plot. Some major pointers were removing border lines from the legend, removing x-axis tick marks, and applying color/shade.↩︎

    4. +
    5. The plot used to look like this: ↩︎

    6. +
    +
    + + + +
    + +
    +
    + + + + + +
    +

    References

    +
    +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_bar_plot-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_bar_plot-1.png new file mode 100644 index 00000000..e3e48b4f Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_bar_plot-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_pointplot-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_pointplot-1.png new file mode 100644 index 00000000..24b59b2f Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_pointplot-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-3-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-3-1.png new file mode 100644 index 00000000..fc3eedff Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-3-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-4-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-4-1.png new file mode 100644 index 00000000..62fb12da Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-4-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..9726a340 Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..8274ec3e Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..46ccf8bd Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.4/header-attrs.js b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.4/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.4/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.5/header-attrs.js b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.6/header-attrs.js b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.6/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/header-attrs-2.6/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-20-plot-makeover-1/plot.png b/docs/posts/2020-09-20-plot-makeover-1/plot.png new file mode 100644 index 00000000..f4a3d493 Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/plot.png differ diff --git a/docs/posts/2020-09-20-plot-makeover-1/prev.png b/docs/posts/2020-09-20-plot-makeover-1/prev.png new file mode 100644 index 00000000..78ebbf23 Binary files /dev/null and b/docs/posts/2020-09-20-plot-makeover-1/prev.png differ diff --git a/docs/posts/2020-09-23-tidytuesday-2020-week-39/index.html b/docs/posts/2020-09-23-tidytuesday-2020-week-39/index.html new file mode 100644 index 00000000..b1bf7119 --- /dev/null +++ b/docs/posts/2020-09-23-tidytuesday-2020-week-39/index.html @@ -0,0 +1,2716 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 week 39 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 week 39

    + + + +

    Stacked area plot of the heights of Himalayan peaks attempted over the last century

    +
    + + + +
    + +
    + +
    +

    Visualization

    +
    +

    +
    +

    Things I learned

    +
      +
    • Having a nice background color for the plot (and generally just working with color)

    • +
    • Margin options of various kinds in theme()

    • +
    • Using {scales}, pretty_breaks() in particular

    • +
    • Using {ragg} to draw and save high quality plots

    • +
    +

    Things to improve

    +
      +
    • The subtitle is kinda boring (and the entire plot is a bit underwhelming)

    • +
    • Figure out how to increase spacing between y-axis text and the plot (hjust is relative to each label, so doesn’t work)

    • +
    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +
    +# DATA
    +
    +tuesdata <- tidytuesdayR::tt_load("2020-09-22")
    +
    +climb_data <- tuesdata$expeditions %>% 
    +  left_join(tuesdata$peaks, by = "peak_name") %>% 
    +  select(peak = peak_name, year, height = height_metres) %>% 
    +  arrange(-height) %>% 
    +  mutate(height_group = fct_inorder(case_when(peak == "Everest" ~ "Mt. Everest (8850m)",
    +                                              between(height, 8000, 8849) ~ "> 8000m",
    +                                              between(height, 7000, 7999) ~ "7999m ~ 7000m",
    +                                              between(height, 6000, 6999) ~ "6999m ~ 6000m",
    +                                              TRUE ~ "< 6000m"))
    +  ) %>% 
    +  count(five_years = round(year/5) * 5, height_group) %>% 
    +  filter(five_years >= 1920) %>% 
    +  complete(five_years, height_group, fill = list(n = 0)) %>% 
    +  group_by(five_years) %>% 
    +  mutate(prop = n / sum(n)) %>% 
    +  ungroup()
    +
    +
    +# PLOT
    +
    +mountain_palette <- c("#6E86A6", "#95A2B3", "#5C606A", "#44464E", "#3D3737")
    +
    +climb_plot <- climb_data %>% 
    +  ggplot(aes(five_years, prop)) +
    +  geom_area(aes(fill = height_group, color = height_group))  +
    +  scale_fill_manual(values = mountain_palette) +
    +  scale_color_manual(values = mountain_palette) +
    +  coord_cartesian(xlim = c(1920, 2020), expand = FALSE) +
    +  scale_x_continuous(breaks = scales::pretty_breaks(11)) +
    +  scale_y_continuous(labels = scales::percent) +
    +  labs(
    +    title = "Himalayan Peaks Attempted Over Time",
    +    subtitle = "Over 1/4th of all expeditions were to Mount Everest",
    +    x = NULL, y = NULL, fill = NULL, color = NULL,
    +    caption = "By: @yjunechoe | Source: The Himalayan Database"
    +  ) +
    +  theme_classic(base_family = "Futura Hv BT", base_size = 16) +
    +  theme(
    +    plot.title.position = "plot",
    +    plot.title = element_text(size = 28, color = "white", family = "Lora", face = "bold"),
    +    plot.subtitle = element_text(size = 14, color = "white", face = "italic"),
    +    plot.margin = margin(2, 2.5, 2, 2, 'cm'),
    +    plot.caption = element_text(color = "white", family = "Roboto Mono", hjust = 1.15, vjust = -13),
    +    legend.position = "top",
    +    legend.direction = "horizontal",
    +    legend.text = element_text(color = "white"),
    +    legend.background = element_rect(fill = NA),
    +    axis.text = element_text(color = "white"),
    +    axis.text.y = element_text(vjust = -.1),
    +    axis.text.x = element_text(vjust = -2),
    +    axis.ticks = element_blank(),
    +    axis.line = element_blank(),
    +    panel.background = element_blank(),
    +    plot.background = element_rect(fill = "#606F84", color = NA)
    +  )
    +
    +
    +# SAVE
    +
    +pngfile <- fs::path(getwd(), "plot.png")
    +ragg::agg_png(
    +  pngfile,
    +  width = 60,
    +  height = 36,
    +  units = "cm",
    +  res = 300,
    +  scaling = 2
    +)
    +plot(climb_plot); invisible(dev.off())
    +
    +
    +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-23-tidytuesday-2020-week-39/preview.png b/docs/posts/2020-09-23-tidytuesday-2020-week-39/preview.png new file mode 100644 index 00000000..08835091 Binary files /dev/null and b/docs/posts/2020-09-23-tidytuesday-2020-week-39/preview.png differ diff --git a/docs/posts/2020-09-23-tidytuesday-2020-week-39/tidytuesday-2020-week-39_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-23-tidytuesday-2020-week-39/tidytuesday-2020-week-39_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-23-tidytuesday-2020-week-39/tidytuesday-2020-week-39_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/colorbar-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/colorbar-1.png new file mode 100644 index 00000000..0b3fd287 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/colorbar-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/explicit_args-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/explicit_args-1.png new file mode 100644 index 00000000..aeed71be Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/explicit_args-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointline-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointline-1.png new file mode 100644 index 00000000..6f535c8a Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointline-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointrange_custom-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointrange_custom-1.png new file mode 100644 index 00000000..1a942ffb Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/pointrange_custom-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/simple_data_bar-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/simple_data_bar-1.png new file mode 100644 index 00000000..80c8133c Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/simple_data_bar-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-1-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-1-1.png new file mode 100644 index 00000000..c0209855 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-1-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-10-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-10-1.png new file mode 100644 index 00000000..3009f7d1 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-10-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-11-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-11-1.png new file mode 100644 index 00000000..b284a9f9 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-11-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-13-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-13-1.png new file mode 100644 index 00000000..9093a1f8 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-13-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-15-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-15-1.png new file mode 100644 index 00000000..5a8d4dc2 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-15-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-16-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-16-1.png new file mode 100644 index 00000000..55c617c9 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-16-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-17-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-17-1.png new file mode 100644 index 00000000..a40b429a Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-17-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-18-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-18-1.png new file mode 100644 index 00000000..2cbbefe6 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-18-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-19-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-19-1.png new file mode 100644 index 00000000..973ab015 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-19-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-28-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-28-1.png new file mode 100644 index 00000000..bfbcda21 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-28-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..39cce034 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..057cedbe Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..1a782c1d Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-8-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-8-1.png new file mode 100644 index 00000000..92faa5b4 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-8-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..0351d3f9 Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.3/header-attrs.js b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.3/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.3/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.4/header-attrs.js b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.4/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/demystifying-stat-layers-ggplot2_files/header-attrs-2.4/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/index.html b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/index.html new file mode 100644 index 00000000..5bd1bd10 --- /dev/null +++ b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/index.html @@ -0,0 +1,3157 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Demystifying stat_ layers in {ggplot2} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Demystifying stat_ layers in {ggplot2}

    + + + +

    The motivation behind stat, the distinction between stat and geom, and a case study of stat_summary()

    +
    + + + +
    + +
    + +
    +

    UPDATE 10/5/20: This blog post was featured in the rweekly highlights podcast! Thanks to the rweekly team for a flattering review of my tutorial!

    +

    Introduction

    +

    (Feel free to skip the intro section if you want to get to the point!)

    +

    A powerful concept in the Grammar of Graphics is that variables are mapped onto aesthetics. In {ggplot2}, a class of objects called geom implements this idea. For example, geom_point(mapping = aes(x = mass, y = height)) would give you a plot of points (i.e. a scatter plot), where the x-axis represents the mass variable and the y axis represents the height variable.

    +

    Because geom_*()s1 are so powerful and because aesthetic mappings are easily understandable at an abstract level, you rarely have to think about what happens to the data you feed it. Take this simple histogram for example:

    +
    +
    +
    data("penguins", package = "palmerpenguins")
    +
    +ggplot(data = penguins, mapping = aes(x = body_mass_g)) +
    +  geom_histogram()
    +
    +
    +

    +
    +

    What’s going on here? You might say that the body_mass_g variable is represented in the x-axis. Sure, that’s not wrong. But a fuller explanation would require you to talk about these extra steps under the hood:

    +
      +
    1. The variable mapped to x is divided into discrete bins

    2. +
    3. A count of observations within each bin is calculated

    4. +
    5. That new variable is then represented in the y axis

    6. +
    7. Finally, the provided x variable and the internally calculated y variable is represented by bars that have certain position and height

    8. +
    +

    I don’t mean to say here that you are a total fool if you can’t give a paragraph-long explanation of geom_histogram(). Rather, my intention here is to emphasize that the data-to-aesthetic mapping in GEOM objects is not neutral, although it can often feel very natural, intuitive, and objective (and you should thank the devs for that!). Just think about the many ways in which you can change any of the internal steps above, especially steps 12 and 23, while still having the output look like a histogram.

    +

    This important point rarely crosses our mind, in part because of what we have gotten drilled into our heads when we first started learning ggplot. As beginners we’ve likely experienced the frustration of having all the data we need to plot something, but ggplot just won’t work. You could imagine a beginner today who’s getting frustrated because geom_point(aes(x = mass, y = height)) throws an error with the following data.

    +
    +
      # A tibble: 2 x 4
    +    variable subject1 subject2 subject3
    +    <chr>       <dbl>    <dbl>    <dbl>
    +  1 mass           75       70       55
    +  2 height        154      172      144
    +
    +

    And what would StackOverflow you tell this beginner? You’d probably tell them to put the data in a tidy format4 first.

    +
    +
      # A tibble: 3 x 3
    +    subject  mass height
    +      <dbl> <dbl>  <dbl>
    +  1       1    75    154
    +  2       2    70    172
    +  3       3    55    144
    +
    +

    Now, that’s something you can tell a beginner for a quick and easy fix. But if you still simply think “the thing that makes ggplot work = tidy data”, it’s important that you unlearn this mantra in order to fully understand the motivation behind stat.

    +

    When and why should I use STAT?

    +

    You could be using ggplot every day and never even touch any of the two-dozen native stat_*() functions. In fact, because you’ve only used geom_*()s, you may find stat_*()s to be the esoteric and mysterious remnants of the past that only the developers continue to use to maintain law and order in the depths of source code hell.

    +

    If that describes you, you might wonder why you even need to know about all these stat_*() functions.

    +
    +

    +
    +

    Well, the main motivation for stat is simply this:

    +
    +

    Even though the data is tidy it may not represent the values you want to display5

    +
    +

    The histogram discussion in the previous section was a good example to this point, but here I’ll introduce another example that I think will hit the point home.

    +

    Suppose you have a data simple_data that looks like this:

    +
    +
    +
    simple_data <- tibble(group = factor(rep(c("A", "B"), each = 15)),
    +                      subject = 1:30,
    +                      score = c(rnorm(15, 40, 20), rnorm(15, 60, 10)))
    +
    +
    +
    +
    +
    + +
    +
    +

    And suppose that you want to draw a bar plot where each bar represents group and the height of the bars corresponds to the mean of score for each group.

    +

    If you’re stuck in the mindset of “the data that I feed in to ggplot() is exactly what gets mapped, so I need to tidy it first and make sure it contains all the aesthetics that each geom needs”, you would need to transform the data before piping it in like this:

    +
    +
    +
    simple_data %>%
    +  group_by(group) %>% 
    +  summarize(
    +    mean_score = mean(score),
    +    .groups = 'drop' # Remember to ungroup!
    +  ) %>% 
    +  ggplot(aes(x = group, y = mean_score)) +
    +  geom_col()
    +
    +
    +
    + +
    +

    +
    +

    Where the data passed in looks like this:

    +
    +
      # A tibble: 2 x 2
    +    group mean_score
    +    <fct>      <dbl>
    +  1 A           43.0
    +  2 B           57.5
    +
    +

    Ok, not really a problem there. But what if we want to add in error bars too? Error bars also plot a summary statistic (the standard error), so we’d need make another summary of the data to pipe into ggplot().

    +

    Let’s first plot the error bar by itself, we’re again passing in a transformed data

    +
    +
    +
    simple_data %>% 
    +  group_by(group) %>% 
    +  summarize(
    +    mean_score = mean(score),
    +    se = sqrt(var(score)/length(score)),
    +    .groups = 'drop'
    +  ) %>% 
    +  mutate(
    +    lower = mean_score - se,
    +    upper = mean_score + se
    +  ) %>% 
    +  ggplot(aes(x = group, y = mean_score, ymin = lower, ymax = upper)) +
    +  geom_errorbar()
    +
    +
    +

    +
    +

    Where the transformed data looks like this:

    +
    +
      # A tibble: 2 x 5
    +    group mean_score    se lower upper
    +    <fct>      <dbl> <dbl> <dbl> <dbl>
    +  1 A           43.0  4.37  38.7  47.4
    +  2 B           57.5  2.82  54.7  60.4
    +
    +

    Ok, now let’s try combining the two. One way to do this is to save the data paseed in for the bar plot and the data passed in for the errorbar plot as two separate variables, and then call each in their respective geoms:

    +
    +
    +
    simple_data_bar <- simple_data %>%
    +  group_by(group) %>% 
    +  summarize(
    +    mean_score = mean(score),
    +    .groups = 'drop'
    +  )
    +  
    +simple_data_errorbar <- simple_data %>% 
    +  group_by(group) %>% 
    +  summarize(
    +    mean_score = mean(score),
    +    se = sqrt(var(score)/length(score)),
    +    .groups = 'drop'
    +  ) %>% 
    +  mutate(
    +    lower = mean_score - se,
    +    upper = mean_score + se
    +  )
    +
    +ggplot() +
    +  geom_col(
    +    aes(x = group, y = mean_score),
    +    data = simple_data_bar
    +  ) +
    +  geom_errorbar(
    +    aes(x = group, y = mean_score, ymin = lower, ymax = upper),
    +    data = simple_data_errorbar
    +  )
    +
    +
    +

    +
    +
    +

    +
    +

    Yeah… that code is a mouthful. The above approach is not parsimonious because we keep repeating similar processes in different places.6 If you, like myself, don’t like how this looks, then let this be a lesson that this is the consequence of thinking that you must always prepare a tidy data containing values that can be DIRECTLY mapped to geometric objects.

    +

    And on a more theoretical note, simple_data_bar and simple_data_errorbar aren’t even really “tidy” in the original sense of the term. We need to remind ourselves here that tidy data is about the organization of observations in the data. Under this definition, values like bar height and the top and bottom of whiskers are hardly observations themselves. Rather, they’re abstractions or summaries of the actual observations in our data simple_data which, if you notice, we didn’t even use to make our final plot above!

    +
    +
    +Tidy data is about the organization of observations. +

    +Figure 1: Tidy data is about the organization of observations. +

    +
    +
    +

    So not only is it inefficient to create a transformed dataframe that suits the needs of each geom, this method isn’t even championing the principles of tidy data like we thought.7

    +

    What we should do instead is to take advantage of the fact that our original data simple_data is the common denominator of simple_data_bar and simple_data_errorbar!

    +

    Wouldn’t it be nice if you could just pass in the original data containing all observations (simple_data) and have each layer internally transform the data in appropriate ways to suit the needs of the geom for that layer?

    +

    Oh, so you mean something like this?

    +
    +
    +
    simple_data %>% 
    +  ggplot(aes(group, score)) +
    +  stat_summary(geom = "bar") +
    +  stat_summary(geom = "errorbar")
    +
    +
    +

    +
    +
    +

    +
    +

    Interim Summary #1

    +

    In this section, I built up a tedious walkthrough of making a barplot with error bars using only geom_*()s just to show that two lines of stat_summary() with a single argument can achieve the same without even touching the data through any form of pre-processing.

    +

    So that was a taste of how powerful stat_*()s can be, but how do they work and how can you use them in practice?

    +

    Understanding STAT with stat_summary()

    +

    Let’s analyze stat_summary() as a case study to understand how stat_*()s work more generally. I think that stat_summary() is a good choice because it’s a more primitive version of many other stat_*()s and is likely to be the one that you’d end up using the most for visualizations in data science.

    +

    Before we start, let’s create a toy data to work with. Let’s call this data height_df because it contains data about a group and the height of individuals in that group.

    +
    +
    +
    height_df <- tibble(group = "A",
    +                    height = rnorm(30, 170, 10))
    +
    +
    +
    +
    +
    + +
    +
    +

    We can visualize the data with a familiar geom, say geom_point():

    +
    +
    +
    height_df %>% 
    +  ggplot(aes(x = group, y = height)) +
    +  geom_point()
    +
    +
    +

    +
    +

    As a first step in our investigation, let’s just replace our familiar geom_point() with the scary-looking stat_summary() and see what happens:

    +
    +
    +
    height_df %>% 
    +  ggplot(aes(x = group, y = height)) +
    +  stat_summary()
    +
    +
    +

    +
    +

    Instead of points, we now see a point and a line through that point. And before you get confused, this is actually one geom, called pointrange, not two separate geoms.8 Now that that’s cleared up, we might ask: what data is being represented by the pointrange?

    +

    Answering this question requires us to zoom out a little bit and ask: what variables does pointrange map as a geom? By looking at the documentation with ?geom_pointrange we can see that geom_pointrange() requires the following aesthetics:

    +
      +
    • x or y

    • +
    • ymin or xmin

    • +
    • ymax or xmax

    • +
    +

    So now let’s look back at our arguments in aes(). We said that group is mapped to x and that height is mapped to y. But we never said anything about ymin/xmin or ymax/xmax anywhere. So how is stat_summary() drawing a pointrange if we didn’t give it the required aesthetic mappings?

    +

    Well, a good guess is that stat_summary() is transforming the data to calculate the necessary values to be mapped to pointrange. Here’s one reason for that guess - I’ve been suppressing message throughout this post but if you run the above code with stat_summary() yourself, you’d actually get this message:

    +
    +
      No summary function supplied, defaulting to `mean_se()`
    +
    +

    Huh, a summary function? That sounds promising. Maybe that’s the key to our mystery!

    +

    First, we see from the documentation of stat_summary() that this mean_se() thing is the default value for the fun.data argument (we’ll talk more on this later).

    +

    Next, let’s call it in the console to see what it is:

    +
    +
    +
    mean_se
    +
    +
    +
      function (x, mult = 1) 
    +  {
    +      x <- stats::na.omit(x)
    +      se <- mult * sqrt(stats::var(x)/length(x))
    +      mean <- mean(x)
    +      new_data_frame(list(y = mean, ymin = mean - se, ymax = mean + 
    +          se), n = 1)
    +  }
    +  <bytecode: 0x0000000019292b88>
    +  <environment: namespace:ggplot2>
    +
    +

    Ok, so it’s a function that takes some argument x and a second argument mult with the default value 1.

    +

    Let’s go over what it does by breaking down the function body line by line:

    +
      +
    1. Remove NA values
    2. +
    3. Calculate variable se which is the standard error of the values in x using the equation \(SE = \sqrt{\frac{1}{N}\sum_{i=1}^N(x_i-\bar{x})^2}\)
    4. +
    5. Calculate the variable mean9 which is the mean of x
    6. +
    7. Create a new dataframe with one row, with columns y, ymin, and ymax, where y is the mean of x, ymin is one standard error below the mean, and ymax is one standard error above the mean.10
    8. +
    +

    A cool thing about this is that although mean_se() seems to be exclusively used for internal operations, it’s actually available in the global environment from loading {ggplot2}. So let’s pass height_df to mean_se() and see what we get back!

    +
    +
    +
    mean_se(height_df)
    +
    +
    +
      Error: Elements must equal the number of rows or 1
    +
    +
    +

    +
    +

    Uhhh what?

    +

    Do you see what happened just now? This is actually really important: stat_summary() summarizes one dimension of the data.11 mean_se() threw an error when we passed it our whole data because it was expecting just a vector of the variable to be summarized.

    + +

    Ok now that we’ve went over that little mishap, let’s give mean_se() the vector it wants.

    +
    +
    +
    mean_se(height_df$height)
    +
    +
    +
            y  ymin  ymax
    +  1 171.8 170.3 173.3
    +
    +

    And look at that, these look like they’re the same values that were being represented by the mid-point and the end-points of the pointrange plot that we drew with stat_summary() above!

    +

    You know how else we can check that this is the case? With this neat function called layer_data().

    +

    We can pull the data that was used to draw the pointrange by passing our plot object to layer_data() and setting the second argument to 112:

    +
    +
    +
    pointrange_plot <- height_df %>% 
    +  ggplot(aes(x = group, y = height)) +
    +  stat_summary()
    +
    +layer_data(pointrange_plot, 1)
    +
    +
    +
        x group     y  ymin  ymax PANEL flipped_aes colour size linetype shape fill
    +  1 1     1 171.8 170.3 173.3     1       FALSE  black  0.5        1    19   NA
    +    alpha stroke
    +  1    NA      1
    +
    +

    Would ya look at that! There’s a lot of stuff in there, but it looks like the values for y, ymin, and ymax used for the actual plot match up with the values we calculated with mean_se() above!

    +

    We’ve solved our mystery of how the pointrange was drawn when we didn’t provide all the required mappings!

    +
    +

    +
    +

    Interim Summary #2

    +

    To summarize this section (ha!), stat_summary() works in the following order:

    +
      +
    1. The data that is passed into ggplot() is inherited if one is not provided

    2. +
    3. The function passed into the fun.data argument applies transformations to (a part of) that data (defaults to mean_se())

    4. +
    5. The result is passed into the geom provided in the geom argument (defaults to pointrange).

    6. +
    7. If the data contains all the required mapppings for the geom, the geom will be plotted.

    8. +
    +

    And to make things extra clear & to make stat_summary() less mysterious, we can explicitly spell out the two arguments fun.data and geom that we went over in this section.

    +
    +
    +
    height_df %>% 
    +  ggplot(aes(x = group, y = height)) +
    +  stat_summary(
    +    geom = "pointrange",
    +    fun.data = mean_se
    +  )
    +
    +
    +
    + +
    +

    +
    +

    Look, it’s the same plot!

    +

    Putting STAT to use

    +

    Now we have arrived at the fun part.

    +

    Here, I will demonstrate a few ways of modifying stat_summary() to suit particular visualization needs.

    +

    For this section, I will use a modified version of the penguins data that I loaded all the way up in the intro section (I’m just removing NA values here, nothing fancy).

    +
    +
    +
    my_penguins <- na.omit(penguins)
    +
    +
    +
    +

    At no point in this section will I be modifying the data being piped into ggplot(). That is the beauty and power of stat.

    +

    1. Error bars showing 95% confidence interval

    +

    Here, we’re plotting the mean body_mass_g of penguins for each sex, with error bars that show the 95% confidence interval (a range of approx 1.96 standard errors from the mean).

    +
    +
    +
    my_penguins %>% 
    +  ggplot(aes(sex, body_mass_g)) +
    +  stat_summary(
    +    fun.data = ~mean_se(., mult = 1.96), # Increase `mult` value for bigger interval!
    +    geom = "errorbar",
    +  )
    +
    +
    +
    + +
    +

    +
    +

    The transformed data used for the errorbar geom inside stat_summary():

    +
    +
    +
    bind_rows(
    +  mean_se(my_penguins$body_mass_g[my_penguins$sex == "female"], mult = 1.96),
    +  mean_se(my_penguins$body_mass_g[my_penguins$sex == "male"], mult = 1.96),
    +)
    +
    +
    +
           y ymin ymax
    +  1 3862 3761 3964
    +  2 4546 4427 4665
    +
    +

    2. A color-coded bar plot of medians

    +

    Here, we’re plotting the median bill_length_mm for each penguins species and coloring the groups with median bill_length_mm under 40 in pink.

    +
    +
    +
    calc_median_and_color <- function(x, threshold = 40) {
    +  tibble(y = median(x)) %>% 
    +    mutate(fill = ifelse(y < threshold, "pink", "grey35"))
    +}
    +
    +my_penguins %>% 
    +  ggplot(aes(species, bill_length_mm)) +
    +  stat_summary(
    +    fun.data = calc_median_and_color,
    +    geom = "bar"
    +  )
    +
    +
    +
    + +
    +

    +
    +

    The transformed data used for the bar geom inside stat_summary():

    +
    +
    +
    group_split(my_penguins, species) %>%
    +  map(~ pull(., bill_length_mm)) %>% 
    +  map_dfr(calc_median_and_color)
    +
    +
    +
    + +
    +
      # A tibble: 3 x 2
    +        y fill  
    +    <dbl> <chr> 
    +  1  38.8 pink  
    +  2  49.6 grey35
    +  3  47.4 grey35
    +
    +

    Note how you can calculate non-required aesthetics in your custom functions (e.g., fill) and they also be used to make the geom!

    +

    3. Pointrange plot with changing size

    +

    Here, we’re plotting bill_depth_mm of penguins inhabiting different islands, with the size of each pointrange changing with the number of observations

    +
    +
    +
    my_penguins %>% 
    +  ggplot(aes(species, bill_depth_mm)) +
    +  stat_summary(
    +    fun.data = function(x) {
    +      
    +      scaled_size <- length(x)/nrow(my_penguins)
    +      
    +      mean_se(x) %>% 
    +        mutate(size = scaled_size)
    +    }
    +  )
    +
    +
    +
    + +
    +

    +
    + +

    The transformed data used for the pointrange geom inside stat_summary():

    +
    +
    +
    group_split(my_penguins, species) %>%
    +  map(~ pull(., bill_depth_mm)) %>% 
    +  map_dfr(
    +    function(x) {
    +      
    +      scaled_size <- length(x)/nrow(my_penguins)
    +      
    +      mean_se(x) %>% 
    +        mutate(size = scaled_size)
    +    }
    +  )
    +
    +
    +
            y  ymin  ymax   size
    +  1 18.35 18.25 18.45 0.4384
    +  2 18.42 18.28 18.56 0.2042
    +  3 15.00 14.91 15.09 0.3574
    +
    +

    Conclusion

    +

    Main Ideas

    +
      +
    • Even though the data is tidy, it may not represent the values you want to display

    • +
    • The solution is not to transform your already-tidy data so that it contains those values

    • +
    • Instead, you should pass in your original tidy data into ggplot() as is and allow stat_*() functions to apply transformations internally

    • +
    • These stat_*() functions can be customized for both their geoms and their transformation functions, and works similarly to geom_*() functions in other regards

    • +
    • If you want to use your own custom function, make sure to check the documentation of that particular stat_*() function to check the variable/data type it requires.

    • +
    • If you want to use a different geom, make sure that your transformation function calculates all the required aesthetics for that geom

    • +
    +

    STAT vs. GEOM or STAT and GEOM?

    +

    Although I have talked about the limitations of geom_*()s to demonstrate the usefulness of stat_*()s, both have their place. It’s about knowing when to use which; it’s not a question of either-or. In fact, they require each other - just like how stat_summary() had a geom argument, geom_*()s also have a stat argument. At a higher level, stat_*()s and geom_*()s are simply convenient instantiations of the layer() function that builds up the layers of ggplot.

    +

    Because this is important, I’ll wrap up this post with a quote from Hadley explaining this false dichotomy:

    +
    +

    Unfortunately, due to an early design mistake I called these either stat_() or geom_(). A better decision would have been to call them layer_() functions: that’s a more accurate description because every layer involves a stat and a geom.13

    +
    +
    +
    +
    +
      +
    1. Just to clarify on notation, I’m using the star symbol * here to say that I’m referencing all the functions that start with geom_ like geom_bar() and geom_point(). This is called the Kleene star and it’s used a lot in regex, if you aren’t familiar.↩︎

    2. +
    3. You could have bins of that are not of equal size. Or, you could have bins that bleed into each other to create a rolling window summary.↩︎

    4. +
    5. You could calculate the sum of raw values that are in each bin, or calculate proportions instead of counts↩︎

    6. +
    7. If you aren’t familiar already, “tidy” is a specific term of art↩︎

    8. +
    9. This quote is adapted from Thomas Lin Pedersen’s ggplot2 workshop video↩︎

    10. +
    11. Yes, you can still cut down on the code somewhat, but will it even get as succinct as what I show below with stat_summary()? (9/30 edit) Okay, I was kinda strawmaning, and Hadley(!) has correctly caught me on that. The bar-errorbar plot was not the best choice to demonstrate the benefits of stat_summary(), but I just wanted to get people excited about stat_*()! Sorry for the confusion/irritation!!↩︎

    12. +
    13. There’s actually one more argument against transforming data before piping it into ggplot. When you choose the variables to plot, say cyl and mpg in the mtcars dataset, do you call select(cyl, mpg) before piping mtcars into ggplot? No? Well then why would you transform your data beforehand if you can just have that be handled internally instead? It’s the same logic!↩︎

    14. +
    15. If you’re still skeptical, save the plot object to a variable like plot and call plot$layers to confirm that geom_pointrange was used to draw the plot.↩︎

    16. +
    17. I personally don’t agree with this naming choice since mean is also the name of the base function↩︎

    18. +
    19. The function new_data_frame() is from {vctrs}. That last line of code in the function body is doing the same thing as data.frame(y = mean, ymin = mean - se, ymax = mean + se), but there’s less room for error the way it’s done in the source code.↩︎

    20. +
    21. If you read the documentation, the very first line starts with “stat_summary() operates on unique x or y …” (emphasis mine)↩︎

    22. +
    23. This second argument specifies which layer to return. Here, the pointrange layer is the first and only layer in the plot so I actually could have left this argument out.↩︎

    24. +
    25. Emphasis mine. Source: https://cran.r-project.org/web/packages/ggplot2/vignettes/extending-ggplot2.html↩︎

    26. +
    +
    + + + +
    + +
    +
    + + + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/preview.png b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/preview.png new file mode 100644 index 00000000..85c82b0c Binary files /dev/null and b/docs/posts/2020-09-26-demystifying-stat-layers-ggplot2/preview.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/beetles.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/beetles.png new file mode 100644 index 00000000..28d6d29a Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/beetles.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-1-1.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-1-1.png new file mode 100644 index 00000000..1b110152 Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-1-1.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-2-1.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-2-1.png new file mode 100644 index 00000000..2da1669a Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-2-1.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-3-1.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-3-1.png new file mode 100644 index 00000000..7c1bab8b Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/figure-html5/unnamed-chunk-3-1.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4.4/header-attrs.js b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4.4/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4.4/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4/header-attrs.js b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.4/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.5/header-attrs.js b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.6/header-attrs.js b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.6/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-13-designing-guiding-aesthetics/designing-guiding-aesthetics_files/header-attrs-2.6/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/index.html b/docs/posts/2020-10-13-designing-guiding-aesthetics/index.html new file mode 100644 index 00000000..4bb76418 --- /dev/null +++ b/docs/posts/2020-10-13-designing-guiding-aesthetics/index.html @@ -0,0 +1,2846 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Designing guiding aesthetics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Designing guiding aesthetics

    + + + +

    The fine line between creativity and noise

    +
    + + + +
    + +
    + +
    +

    Visualization

    +
    +

    +
    +

    Reflections on guiding aesthetics

    +

    Admittedly, the plot itself is quite simple, but I learned a lot from this process. So, breaking from the usual format of my tidytuesday blogposts, I want to talk about the background and motivation behind the plot as this was a big step in a new (and exciting!) direction for me that I’d like to document.

    +

    Just for clarification, I’m using the term guiding aesthetics to refer to elements of the plot that do not represent a variable in the data, but serves to emphasize the overall theme or topic of the being visualized. So the mountains in my plot do not themselves contain any data, but it’s the thing that tells readers that the plot is about mountains (a valuable, but different kind of info!). But more on that later.

    +

    Why bother with guiding aesthetics?

    +

    This was my first time adding a huge element to a plot that wasn’t meaningful, in the sense of representing the data. As someone in academia working on obscure topics (as one does in academia), I’m a firm believer in making your plots as simple and minimal as possible. So I, like many others, think that it’s always a huge risk to add elements that are not absolutely necessary.

    +

    But as you might imagine, I first fell in love with data visualization not because of how objective and straightforward they are, but because of how eye-catching they can be. Like, when I was young I used to be really into insects. In fact, I read insect encyclopedias as a hobby. That TMI is relevant because those are full of data(!) visualizations that employ literal mappings of data, since those are easy to interpret for children. For example, consider the following diagram of the life cycle of the Japanese beetle from the USDA.

    +
    +
    +Diagram of the life cycle of the Japanese beetle +

    +Figure 1: Diagram of the life cycle of the Japanese beetle +

    +
    +
    +

    As a child, I never appreciated/realized all the data that was seamlessly packed into diagrams like this. But with my Grammar of Graphics lens on, I can now see that:

    +
      +
    • The developmental stage at each month is mapped to x
    • +
    • The depth at which the developing beetle lives at each stage is mapped to y
    • +
    • The appearance of the beetle at each developmental stage is mapped to shape
    • +
    • The size of the beetle at each developmental stage is mapped to, well, size
    • +
    +

    But I could have easily plotted something like this instead:

    +
    +
    +
    beetles <- tibble::tribble(
    +  ~Month, ~Depth,   ~Stage, ~Size,
    +   "JAN",    -10,  "Larva",    10,
    +   "FEB",     -8,  "Larva",    12,
    +   "MAR",     -7,  "Larva",    14,
    +   "APR",     -7,  "Larva",    14,
    +   "MAY",     -6,   "Pupa",    11,
    +   "JUN",      0, "Beetle",    12,
    +   "JUL",      0, "Beetle",    12,
    +   "AUG",     -3,  "Larva",     1,
    +   "SEP",     -2,  "Larva",     2,
    +   "OCT",     -1,  "Larva",     4,
    +   "NOV",     -3,  "Larva",     5,
    +   "DEC",     -8,  "Larva",     7
    +)
    +
    +beetles$Month <- fct_inorder(beetles$Month)
    +
    +ggplot(beetles, aes(x = Month, y = Depth, size = Size, shape = Stage)) +
    +  geom_point() +
    +  ggtitle("The lifecycle of the Japanese beetle")
    +
    +
    +

    +
    +

    Both visuals represent the data accurately, but of course the diagram looks better. And not just because it’s complex, but also because it exploits the associations between aesthetic dimensions and their meanings, as well as the strength of those associations.

    +

    For example, the shape dimension literally corresponds to shape, and the shape of the different developmental stages of the beetle are unique enough for there to be interesting within-stage variation and still be recognizable - e.g., the beetle looks different crawling out the ground in June and entering back in August, but it’s still recognizable as a beetle (and the same beetle at that!). This would’ve been difficult if the variable being mapped to shape was something arbitrary and abstract, like the type of protein that’s most produced at a particular stage. The diagram thus exploits the strength of the association between the shape dimension and the literal shapes of the beetle to represent the developmental stages. And it should be clear now that the same goes for y and size.

    +

    How about x? There’s no such strong/literal interpretation of the x-dimension - at best it just means something horizontal. So it’s actually fitting that a similarly abstract concept like the passage of time is mapped to x. We understand time linearly, and often see time as the x-axis in other plots, so it fits pretty naturally here.

    +

    Lastly, let’s talk about the color dimension. Even though no information was actually mapped to color, we certainly are getting some kind of information from the colors used in the plot. Literally put, we’re getting the information that the grass is green and the soil is brown. Now, that information is actually not representing any data that we care about so it’s technically visual noise, but it helps bring forward the overall theme of the diagram. While this worked out in the end, notice now that you have effectively thrown out color as a dimension that can convey meaningful information. That was a necessary tradeoff, but a well motivated one, since the information that the diagram is trying to convey doesn’t really need color.

    +

    Designing guiding aesthetics

    +

    I’m hardly the expert, but I found it helpful to think of the process as mediating the tug of war between the guiding aesthetic and the variables in the data as they fight over space in different mapping dimensions.

    +

    This meant I had to make some changes to my usual workflow for explanatory data visualization, which mostly goes something like this:

    +
      +
    1. Take my response variable and map it to y
    2. +
    3. Figure out the distribution of my response variables and choose the geom (e.g., boxplot, histogram).
    4. +
    5. Map my dependent variables to other dimensions - this usually ends at either just x or x + facet groupings
    6. +
    +

    But if I’m trying to incorporate guiding aesthetics, my workflow would look more like this:

    +
      +
    1. Start with a couple ideas for a visual representation of the topic (scenes, objects, etc.)
    2. +
    3. Figure out the dimensions that the variables in the data can be mapped to
    4. +
    5. Figure out the dimensions that each visual representation would intrude in
    6. +
    7. Make compromises between (2) and (3) in a way that maximizes the quality of the data and the visual representation
    8. +
    +

    Of course, this kind of flexibility is unique to exploratory data visualization, in particular to the kinds where none of the variable is significant or interesting a priori. Of course in real life there will be a lot more constraints, but because we can assume a great degree of naivety towards the data for #tidytuesday, I get to pick and choose what I want to plot (which makes #tidytuesday such a great place to practice baby steps)!

    +

    For illustration, here’s my actual thought process while I was making the #tidytuesday plot.

    +

    WARNING: a very non-linear journey ahead!

    +

    My thought process

    +

    The topic was about Himalayan climbing expeditions, so I wanted my visual to involve a mountain shape. The most obvious idea that came to mind was to draw a mountain where the peak of that mountain corresponded with their height_metres, a variable from the peaks data. It’s straightforward and intuitive! So I drew a sketch (these are the original rough sketches - please forgive the quality!)

    +
    +
    +The first guiding aesthetic idea +

    +Figure 2: The first guiding aesthetic idea +

    +
    +
    +

    But this felt… a bit empty. I threw in Mount Everest, but now what? I still had data on hundreds of more Himalayan peaks that were in the dataset. Just visualizing Mount Everest is not badly motivated per se (it’s the most famous peak afterall), but it wouldn’t make an interesting plot since there wasn’t much data on individual peaks. I wanted to add a few more mountain shapes, but I struggled to find a handful of peaks that formed a coherent group. I knew that if I wanted to go with the idea of mountain shapes as the guiding aesthetic, I could only manage to fit about a dozen or so without it looking too crowded.

    +

    I put that issue aside for the moment and moved on while trying to accommodate for the possibility that I may have to fit in many more peaks. I thought about having a single mountain shape just for Mount Everest, and a point with a vertical spikeline for all other peaks to emphasize the y-axis representing height_metres.

    +
    +
    +The second guiding aesthetic idea +

    +Figure 3: The second guiding aesthetic idea +

    +
    +
    +

    At this point I started thinking about the x-axis. If I do use points to represent peaks (specifically, peak height), where would I actually position each point? Just randomly along the x-axis? It really started hitting me at this point that the quality of my data was pretty abysmal. Even if I ended up with a pretty visualization, I didn’t think I could justify calling it a data visualization. I felt that it’d be a reach to use complex visuals just to communicate a single variable.

    +

    I toyed around with enriching the data being plotted. What if I use size of the dots to represent the average age of climbers who reached the peak, from the memmbers data? Or what if I used shape of country flags on top of the dots to represent the country that first reached the peak, from the expeditions data?

    +

    These were all cool ideas, but I kept coming back to the need to make the x-dimension meaningful. It just stood out too much. I didn’t think I could prevent the reader from expecting some sort of a meaning from the positioning of the dots along the x-axis.

    +

    So I went back to Step #2. I gathered up all the continuous variables across the three data in the #tidytuesday dataset (peaks, members, expeditions) and evaluated how good of a candidate each of them were for being mapped to x. This was the most time-consuming part of the process, and I narrowed it down to three candidates:

    +
      +
    • expeditions$members: looked okay at first, but once I started aggregating (averaging) by peak, the distribution became quite narrow. That made it less interesting and not very ideal for mountain shapes (the typical mountain shape is wider than they are tall).
    • +
    • members$age: has a nice distribution and a manageable range with no extreme outliers.
    • +
    • peaks$first_ascent_year: also has the above features + doesn’t need to be aggregated in some way, so the x-axis would have a very straight forward interpretation.
    • +
    +

    The first_ascent_year variable looked the most promising, so that’s what I pursued (and ended up ultimately adopting!).

    +
    +
    +The third guiding aesthetic idea +

    +Figure 4: The third guiding aesthetic idea +

    +
    +
    +

    Now I felt like I had more direction to tackle the very first issue that I ran into during this process: the problem of picking out a small set of peaks that were interesting and well-motivated. I played around more with several options, but I ultimately settled on something very simple - the top 10 most popular peaks. Sure it’s overused and not particularly exciting, but that was a sacrifice that my over-worked brain was willing to make at the time.

    +

    And actually, it turned out to be a great fit with my new x variable! It turns out that the top 10 most climbed peaks are also those that were among the first to be climbed (a correlation that sorta makes sense), so this set of peaks had an additional benefit of localizing the range of x to between the 1940s-1960s. And because 10 was a manageable number, I went ahead with my very first idea of having a mountain accompanying each point, where the peaks represent the peak of the guiding aesthetic (the mountain shape) as well as the height_metres and first_ascent_year.

    +

    Finally, it came time for me to polish up on the mountains. I needed to decide on features of the mountains like how wide the base is, how many valleys and peaks it has, how tall the peaks are relative to each other, etc. I had to be careful that these superfluous features do not encroach on the dimensions where I mapped my data to - the x and y. Here, I had concerns about two of the mountain features in particular: base width and smaller peaks:

    +
      +
    • The base width was troubling because how wide the base of the mountain stretches could be interpreted as representing another variable that has to do with year (like the first and last time it was climbed, for example). This was a bit difficult to deal with, but I settled on a solution which was to keep the base width constant. By not having that feature vary at all, I could suppress any expectation for it to carry some sort of meaning. It’s kind of like how when you make a scatterplot with variables mapped to x and y, you don’t imbue any special meaning to the fact that the observations are represented by a circle (point), beacuse all of them are that shape. If they varied in any way, say you also have some rectangles and triangles, then you’d start expecting the shape to represent something meaningful.

    • +
    • The smaller peaks of the mountain shapes were troubling because I was already using the peak to represent the height. It helped that the actual peaks representing the data were also marked by a point and a label of the peak name. But to make it extra clear that the they were pure noise, I decided to randomly generate peaks and valleys, and tried to make that obvious. In the code attached at the bottom of this post, several parameters of the mountain-generating function allowed me to do this. It also helped that I added a note saying that the mountains were randomly generated when I tweeted it, which is kind of cheating perhaps, but it worked!

    • +
    + + +

    That wraps up my long rant on how I made my mountains plot! For more context, making the plot took about a half a day worth of work, which isn’t too bad for a first attempt! Definitely looking forward to getting more inspirations like this in the future.

    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +
    +make_mountain <- function(x_start, x_end, base = 0, peak_x, peak_y, n_peaks = 3, peaks_ratio = 0.3, side.first = "left") {
    +  
    +  midpoint_abs <- (peak_y - base)/2 + base
    +  midpoint_rel <- (peak_y - base)/2
    +  
    +  side_1_n_peaks <- floor(n_peaks/2)
    +  side_2_n_peaks <- n_peaks - side_1_n_peaks -1
    +  
    +  side_1_x <- seq(x_start, peak_x, length.out = side_1_n_peaks * 2 + 2)
    +  side_1_x <- side_1_x[-c(1, length(side_1_x))]
    +  
    +  side_2_x <- seq(peak_x, x_end, length.out = side_2_n_peaks * 2 + 2)
    +  side_2_x <- side_2_x[-c(1, length(side_2_x))]
    +  
    +  side_1_y <- numeric(length(side_1_x))
    +  side_1_y[c(TRUE, FALSE)] <- runif(length(side_1_y)/2, midpoint_abs, midpoint_abs + midpoint_rel * peaks_ratio)
    +  side_1_y[c(FALSE, TRUE)] <- runif(length(side_1_y)/2, midpoint_abs - midpoint_rel * peaks_ratio, midpoint_abs)
    +  
    +  side_2_y <- numeric(length(side_2_x))
    +  side_2_y[c(TRUE, FALSE)] <- runif(length(side_2_y)/2, midpoint_abs, midpoint_abs + midpoint_rel * peaks_ratio)
    +  side_2_y[c(FALSE, TRUE)] <- runif(length(side_2_y)/2, midpoint_abs - midpoint_rel * peaks_ratio, midpoint_abs)
    +  
    +  if (side.first == "left") {
    +    side_left <- data.frame(x = side_1_x, y = side_1_y)
    +    side_right <- data.frame(x = side_2_x, y = rev(side_2_y))
    +  } else if (side.first == "right") {
    +    side_left <- data.frame(x = side_2_x, y = side_2_y)
    +    side_right <- data.frame(x = side_1_x, y = rev(side_1_y))
    +  } else {
    +    error('Inavlid value for side.first - choose between "left" (default) or "right"')
    +  }
    +  
    +  polygon_points <- rbind(
    +    data.frame(x = c(x_start, peak_x, x_end), y = c(base, peak_y, base)),
    +    side_left,
    +    side_right
    +  )
    +  
    +  polygon_points[order(polygon_points$x),]
    +
    +}
    +
    +tuesdata <- tidytuesdayR::tt_load("2020-09-22")
    +
    +peaks <- tuesdata$peaks
    +expeditions <- tuesdata$expeditions
    +
    +top_peaks <- expeditions %>% 
    +  count(peak_name) %>% 
    +  slice_max(n, n = 10)
    +
    +plot_df <- peaks %>% 
    +  filter(peak_name %in% top_peaks$peak_name) %>% 
    +  arrange(-height_metres) %>% 
    +  mutate(peak_name = fct_inorder(peak_name))
    +
    +plot_df %>% 
    +  ggplot(aes(x = first_ascent_year, y = height_metres)) +
    +  pmap(list(plot_df$first_ascent_year, plot_df$height_metres, plot_df$peak_name),
    +       ~ geom_polygon(aes(x, y, fill = ..3), alpha = .6,
    +                      make_mountain(x_start = 1945, x_end = 1965, base = 5000,
    +                                    peak_x = ..1, peak_y = ..2, n_peaks = sample(3:5, 1)))
    +  ) +
    +  geom_point(color = "white") +
    +  ggrepel::geom_text_repel(aes(label = peak_name),
    +                           nudge_y = 100, segment.color = 'white',
    +                           family = "Montserrat", fontface = "bold", color = "white") +
    +  guides(fill = guide_none()) +
    +  scale_x_continuous(expand = expansion(0.01, 0)) +
    +  scale_y_continuous(limits = c(5000, 9000), expand = expansion(0.02, 0)) +
    +  theme_minimal(base_family = "Montserrat", base_size = 12) +
    +  labs(title = "TOP 10 Most Attempted Himalayan Peaks",
    +       x = "First Ascent Year", y = "Peak Height (m)") +
    +  palettetown::scale_fill_poke(pokemon = "articuno") +
    +  theme(
    +    plot.title.position = "plot",
    +    plot.title = element_text(size = 24, vjust = 3, family = "Lora"),
    +    text = element_text(color = "white", face = "bold"),
    +    axis.text = element_text(color = "white"),
    +    axis.title = element_text(size = 14),
    +    axis.title.x = element_text(vjust = -2),
    +    axis.title.y = element_text(vjust = 4),
    +    plot.margin = margin(1, .5, .7, .7, "cm"),
    +    plot.background = element_rect(fill = "#5C606A", color = NA),
    +    panel.grid = element_blank(),
    +  )
    +
    +
    +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain1.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain1.png new file mode 100644 index 00000000..2c5ed9e5 Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain1.png differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain2.jpg b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain2.jpg new file mode 100644 index 00000000..7aa3a658 Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain2.jpg differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain3.jpg b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain3.jpg new file mode 100644 index 00000000..af4b7010 Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/mountain3.jpg differ diff --git a/docs/posts/2020-10-13-designing-guiding-aesthetics/preview.png b/docs/posts/2020-10-13-designing-guiding-aesthetics/preview.png new file mode 100644 index 00000000..52f29bcb Binary files /dev/null and b/docs/posts/2020-10-13-designing-guiding-aesthetics/preview.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/HSV.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/HSV.png new file mode 100644 index 00000000..2aad37fe Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/HSV.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-11-1.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-11-1.png new file mode 100644 index 00000000..17d7d553 Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-11-1.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-15-1.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-15-1.png new file mode 100644 index 00000000..ebd0a9ce Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-15-1.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-16-1.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-16-1.png new file mode 100644 index 00000000..d6fe4c74 Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-16-1.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..f4fa0f3e Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.4.4/header-attrs.js b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.4.4/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.4.4/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.5/header-attrs.js b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/analysis-of-everycolorbots-tweets_files/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/index.html b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/index.html new file mode 100644 index 00000000..5ed4c310 --- /dev/null +++ b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/index.html @@ -0,0 +1,3124 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Analysis of @everycolorbot's tweets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Analysis of @everycolorbot’s tweets

    + + + +

    And why you should avoid neon colors

    +
    + + + +
    +
    + +
    +

    Introduction

    +
    + +
    +

    I, along with nearly two-hundred thousand other people, follow @everycolorbot on twitter. @everycolorbot is a twitter bot that tweets an image of a random color every hour (more details on github). It’s 70% a source of inspiration for new color schemes, and 30% a comforting source of constant in my otherwise hectic life.

    +

    What I’ve been noticing about @everycolorbot’s tweets is that bright, highly saturated neon colors (yellow~green) tend to get less likes compared to cool blue colors and warm pastel colors. You can get a feel of this difference in the number of likes between the two tweets below, tweeted an hour apart:

    +
    +
    + + +
    +
    + + +
    +
    +

    This is actually not a big surprise. Bright pure colors are very harsh and straining to the eye, especially on a white background.1 For this reason bright colors are almost never used in professional web design, and are also discouraged in data visualization.

    +

    So here’s a mini experiment testing that claim: I’ll use @everycolorbot’s tweets (more specifically, the likes on the tweets) as a proxy for likeability/readability/comfortableness/etc. It’ll be a good exercise for getting more familiar with different colors! I’m also going to try a simple descriptive analysis using the HSV color representation, which is a psychologically-motivated mental model of color that I like a lot (and am trying to get a better feel for).

    +
    +
    +HSV cylinder +

    +Figure 1: HSV cylinder +

    +
    +
    +

    Setup

    +

    Using {rtweet} requires authentication from twitter. The steps to do so are very well documented on the package website so I wouldn’t expect too much trouble setting it up if it’s your first time using it. But just for illustration, here’s what my setup looks like:

    +
    +
    +
    api_key <- 'XXXXXXXXXXXXXXXXXXXXX'
    +api_secret_key <- 'XXXXXXXXXXXXXXXXXXXXX'
    +access_token <- "XXXXXXXXXXXXXXXXXXXXX"
    +access_token_secret <- "XXXXXXXXXXXXXXXXXXXXX"
    +
    +token <- create_token(
    +  app = "XXXXXXXXXXXXXXXXXXXXX",
    +  consumer_key = api_key,
    +  consumer_secret = api_secret_key,
    +  access_token = access_token,
    +  access_secret = access_token_secret
    +)
    +
    +
    +
    +

    After authorizing, I queried the last 10,000 tweets made by @everycolorbot. It ended up only returning about a 1/3 of that because the twitter API only allows you to go back so far in time, but that’s plenty for my purposes here.

    +
    + +
    +
    +
    +
    colortweets <- rtweet::get_timeline("everycolorbot", 10000)
    +
    +dim(colortweets)
    +
    +
    +
    +
    +
      [1] 3238   90
    +
    +

    As you see above, I also got back 90 variables (columns). I only care about the time of the tweet, the number of likes it got, and the color it tweeted, so those are what I’m going to grab. I also want to clean things up a bit for plotting, so I’m going to grab just the hour from the time and just the hex code from the text.

    +
    +
    +
    colortweets_df <- colortweets %>% 
    +  select(created_at, text, favorite_count) %>%
    +  mutate(
    +    created_at = lubridate::hour(created_at),
    +    text = paste0("#", str_extract(text, "(?<=0x).*(?= )"))
    +  ) %>% 
    +  rename(
    +    likes = favorite_count,
    +    hour = created_at,
    +    hex = text
    +  )
    +
    +
    +
    +

    And here’s what we end up with:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +likes + +hour + +hex +
    +36 + +15 + +#65f84e +
    +65 + +14 + +#32fc27 +
    +89 + +13 + +#997e13 +
    +140 + +12 + +#ccbf09 +
    +303 + +11 + +#665f84 +
    +75 + +10 + +#b32fc2 +
    +
    +

    Here is the link to this data if you’d like to replicate or extend this analysis yourself.

    +

    Analysis

    +

    Below is a bar plot of colors where the height corresponds to the number of likes. It looks cooler than your usual bar plot because I transformed the x dimension into polar coordinates. My intent in doing this was to control for the hour of day in my analysis and visualize it like a clock (turned out better than expected!)

    +
    +
    +
    colortweets_df %>% 
    +  arrange(-likes) %>% 
    +  ggplot(aes(hour, likes, color = hex)) +
    +  geom_col(
    +    aes(size = likes),
    +    position = "dodge",
    +    show.legend = FALSE
    +  ) +
    +  scale_color_identity() +
    +  theme_void() +
    +  theme(
    +    plot.background = element_rect(fill = "#222222", color = NA),
    +  ) +
    +  coord_polar()
    +
    +
    +
    + +
    +

    +
    +

    I notice at least two interesting contrasts in this visualization:

    +
      +
    • Neon colors (yellow, green, pink) and dark brown and black seems to dominate the center (least liked colors) while warm red~blue pastel colors dominate around the edges (most liked colors)

    • +
    • There also seems to be a distinction between pure blue and red in the inner-middle circle vs. the green~blue pastel colors in the outer-middle circle.

    • +
    +

    So maybe we can say that there are four clusters here:

    +
      +
    1. Least liked: Bright neon colors + highly saturated dark colors

    2. +
    3. Lesser liked: Bright pure/near-pure colors

    4. +
    5. More liked: Darker pastel RGB

    6. +
    7. Most liked: Lighter pastel mixed colors

    8. +
    +

    Now’s let’s try to quantitatively describe each cluster.

    +

    First, as a sanity check, I’m just gonna eyeball the range of likes for each cluster using an un-transformed version of the above plot with units. I think we can roughly divide up the clusters at 100 likes, 200 likes, and 400 likes.

    +
    +
    +
    colortweets_df %>% 
    +  arrange(-likes) %>% 
    +  ggplot(aes(hour, likes, color = hex)) +
    +  geom_col(
    +    aes(size = likes),
    +    position = "dodge",
    +    show.legend = FALSE
    +  ) +
    +  geom_hline(
    +    yintercept = c(100, 200, 400), 
    +    color = "white", 
    +    linetype = 2, 
    +    size = 2
    +  ) +
    +  scale_y_continuous(breaks = scales::pretty_breaks(10)) +
    +  scale_color_identity() +
    +  theme_void() +
    +  theme(
    +    plot.background = element_rect(fill = "#222222", color = NA),
    +    axis.line.y = element_line(color = "white"),
    +    axis.text.y = element_text(
    +      size = 14,
    +      color = "white",
    +      margin = margin(l = 3, r = 3, unit = "mm")
    +    )
    +  )
    +
    +
    +

    +
    +

    If our initial hypothesis about the four clusters are true, we should see these clusters having distinct profiles. Here, I’m going to use the HSV representation to quantitatively test this. To convert our hex values into HSV, I use the as.hsv() function from the {chroma} package - an R wrapper for the javascript library of the same name.

    +
    +
    +
    colortweets_df_hsv <- colortweets_df %>% 
    +  mutate(hsv = map(hex, ~as_tibble(chroma::as.hsv(.x)))) %>% 
    +  unnest(hsv)
    +
    +
    +
    + +

    And now we have the HSV values (hue, saturation, value)!

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +likes + +hour + +hex + +h + +s + +v +
    +36 + +15 + +#65f84e + +111.88235 + +0.6854839 + +0.9725490 +
    +65 + +14 + +#32fc27 + +116.90141 + +0.8452381 + +0.9882353 +
    +89 + +13 + +#997e13 + +47.91045 + +0.8758170 + +0.6000000 +
    +140 + +12 + +#ccbf09 + +56.00000 + +0.9558824 + +0.8000000 +
    +303 + +11 + +#665f84 + +251.35135 + +0.2803030 + +0.5176471 +
    +75 + +10 + +#b32fc2 + +293.87755 + +0.7577320 + +0.7607843 +
    +
    +

    What do we get if we average across the dimensions of HSV for each cluster?

    +
    +
    +
    colortweets_df_hsv <- colortweets_df_hsv %>% 
    +  mutate(
    +    cluster = case_when(
    +      likes < 100 ~ "Center",
    +      between(likes, 100, 200) ~ "Inner-Mid",
    +      between(likes, 201, 400) ~ "Outer-Mid",
    +      likes > 400 ~ "Edge"
    +    ),
    +    cluster = fct_reorder(cluster, likes)
    +  )
    +
    +colortweets_df_hsv %>% 
    +  group_by(cluster) %>% 
    +  summarize(across(h:v, mean), .groups = 'drop')
    +
    +
    +
      # A tibble: 4 x 4
    +    cluster       h     s     v
    +  * <fct>     <dbl> <dbl> <dbl>
    +  1 Center     121. 0.770 0.710
    +  2 Inner-Mid  191. 0.734 0.737
    +  3 Outer-Mid  197. 0.589 0.710
    +  4 Edge       249. 0.304 0.832
    +
    +

    This actually matches up pretty nicely with our initial analysis! We find a general dislike for green colors (h value close to 120) over blue colors (h value close to 240), as well as a dislike for highly saturated colors (intense, bright) over those with low saturation (which is what gives off the “pastel” look). To help make the hue values more interpretable, here’s a color wheel with angles that correspond to the hue values in HSV.2

    +
    +
    +Hue color wheel +

    +Figure 2: Hue color wheel +

    +
    +
    +

    But we also expect to find within-cluster variation along HSV. In particular, hue is kind of uninterpretable on a scale so it probably doesn’t make a whole lot of sense to take a mean of that. So back to the drawing plotting board!

    +

    Since saturation and value do make more sense on a continuous scale, let’s draw a scatterplot for each cluster with saturation on the x-axis and value on the y-axis. I’m also going to map hue to the color of each point, but since hue is abstract on its own, I’m actually just going to replace it with the hex values (i.e., the actual color).

    +
    +
    +
    colortweets_df_hsv %>% 
    +  ggplot(aes(s, v, color = hex)) +
    +  geom_point() +
    +  scale_color_identity() +
    +  lemon::facet_rep_wrap(~cluster) +
    +  theme_void(base_size = 16, base_family = "Montserrat Medium") +
    +  theme(
    +    plot.margin = margin(3, 5, 5, 5, "mm"),
    +    strip.text = element_text(margin = margin(b = 3, unit = "mm")),
    +    panel.border = element_rect(color = "black", fill = NA),
    +    panel.background = element_rect(fill = "grey75", color = NA)
    +  )
    +
    +
    +

    +
    +

    Here’s the mappings spelled out again:

    +
      +
    • saturation (how colorful a color is) is mapped to the X-dimension
    • +
    • value (how light a color is) is mapped to the Y-dimension
    • +
    • hex (the actual color itself) is mapped to the COLOR dimension
    • +
    +


    +

    Our plot above reinforce what we’ve found before. Colors are more likeable (literally) the more they…

    +
      +
    1. Move away from green: Neon-green dominates the least-liked cluster, and that’s a blatant fact. Some forest-greens survive to the lesser-liked cluster, but is practically absent in the more-liked cluster and most-liked cluster. It looks like the only way for green to be redeemable is to either mix in with blue to become cyan and turquoise, which dominates the more-liked cluster, or severly drop in saturation to join the ranks of other pastel colors in the most-liked cluster.

    2. +
    3. Increase in value and decrease in saturation: It’s clear that the top-left corner is dominated by the more-liked and the most-liked cluster. That region is, again, where pastel colors live. They’re calmer than the bright neon colors that plague the least-liked cluster, and are more liked than highly-saturated and intense colors like those in the top right of the Outer-Mid panel. So perhaps this is a lesson that being “colorful” can only get you so far.

    4. +
    +

    Conclusion

    +

    Obviously, all of this should be taken with a grain of salt. We don’t know the people behind the likes - their tastes, whether they see color differently, what medium they saw the tweet through, their experiences, etc.

    +

    And of course, we need to remind ourselves that we rarely see a color just by itself in the world. It contrasts and harmonizes with other colors in the environment in very complex ways.

    +

    But that’s what kinda makes our analysis cool - despite all these complexities, we see evidence for many things that experts working with color emphasize: avoid pure neon, mix colors, etc. This dataset also opens us up to many more types of analyses (like an actual cluster analysis) that might be worth looking into.

    +

    Good stuff.

    +
    +
    +
    +
      +
    1. Dark mode ftw!↩︎

    2. +
    3. While all color wheels look the same, they aren’t all oriented the same. When using HSV, make sure to reference the color wheel where the red is at 0, green is as 120, and blue is at 240.↩︎

    4. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/preview.png b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/preview.png new file mode 100644 index 00000000..a4be4888 Binary files /dev/null and b/docs/posts/2020-10-22-analysis-of-everycolorbots-tweets/preview.png differ diff --git a/docs/posts/2020-10-28-tidytuesday-2020-week-44/index.html b/docs/posts/2020-10-28-tidytuesday-2020-week-44/index.html new file mode 100644 index 00000000..a695a49a --- /dev/null +++ b/docs/posts/2020-10-28-tidytuesday-2020-week-44/index.html @@ -0,0 +1,2758 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 week 44 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 week 44

    + + + +

    Patched animation of the location and cumulative capacity of wind turbines in Canada

    +
    + + + +
    + +
    + +
    +

    Visualization

    +
    +

    +
    +

    Things I learned

    +
      +
    • Using {magick} for animation composition, thanks to the {gganimate} wiki

    • +
    • The very basics of working with spatial data with {rnaturalearth} and {sf}1

    • +
    • A bit about color schemes for maps (I particularly love this color as a way of de-emphasizing territories in the background)

    • +
    +

    Things to improve

    +
      +
    • I couldn’t figure out how to add margins to the bottom, but I now realize that I could’ve just played around with expansion() for the y-axis of the bar animation plot.

    • +
    • Image composition took a while to render, which was a bit frustrating. Need to find a way to speed that up.

    • +
    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +library(gganimate)
    +library(extrafont)
    +
    +tuesdata <- tidytuesdayR::tt_load(2020, week = 44)
    +
    +wind_turbine <- tuesdata$`wind-turbine` %>% 
    +  select(
    +    ID = objectid,
    +    Province = province_territory,
    +    Capacity = total_project_capacity_mw,
    +    Diameter = rotor_diameter_m,
    +    Height = hub_height_m,
    +    Year = commissioning_date,
    +    Lat = latitude,
    +    Lon = longitude
    +  ) %>% 
    +  arrange(Year, -Diameter) %>% 
    +  mutate(
    +    Year = as.integer(str_match(Year, "^\\d{4}")[,1])
    +  )
    +
    +
    +
    +ne_map <- rnaturalearth::ne_countries(scale='medium', returnclass = 'sf')
    +
    +turbine_anim <- wind_turbine %>% 
    +  ggplot() +
    +  geom_rect(
    +    aes(xmin = -150, xmax = -50, ymin = 40, ymax = 72),
    +    fill = "#B6D0D1"
    +  ) +
    +  geom_sf(
    +    aes(fill = ifelse(admin == "Canada", "#7BC86C", "#FFF8DC")),
    +    show.legend = FALSE,
    +    data = filter(ne_map, admin %in% c("Canada", "United States of America"))
    +  ) +
    +  scale_fill_identity() +
    +  geom_point(
    +    aes(Lon, Lat, group = ID, size = Capacity),
    +    show.legend = FALSE, alpha = 0.5, color = "#3C59FF"
    +  ) +
    +  geom_text(
    +    aes(x = -138, y = 43, label = as.character(Year)),
    +    size = 24, color = "grey35", family = "Roboto Slab"
    +  ) +
    +  geom_rect(
    +    aes(xmin = -150, xmax = -50, ymin = 40, ymax = 72),
    +    fill = "transparent", color = "black"
    +  ) +
    +  coord_sf(
    +    xlim = c(-150, -50),
    +    ylim = c(40, 72),
    +    expand = FALSE,
    +    clip = "on"
    +  ) +
    +  ggtitle("Canadian Wind Turbines") +
    +  theme_void() +
    +  theme(
    +    plot.title = element_text(family = "Adelle", s),
    +    plot.margin = margin(1, 1, 1, 1, "cm")
    +  ) +
    +  transition_reveal(Year)
    +
    +animate(turbine_anim, width = 1000, height = 600, nframes = 100)
    +
    +
    +
    +capacity_data <- wind_turbine %>% 
    +  group_by(Year) %>% 
    +  summarize(
    +    Capacity = sum(Capacity),
    +    .groups = 'drop'
    +  ) %>% 
    +  mutate(
    +    Capacity = accumulate(Capacity, sum),
    +    width = (Capacity/max(Capacity)) * 70
    +  )
    +
    +capacity_anim <- capacity_data %>% 
    +  ggplot(aes(x = 1, y = Capacity)) +
    +  geom_col(
    +    fill = "#3C59FF",
    +  ) +
    +  geom_text(
    +    aes(label = paste(as.character(round(Capacity * 0.001)), "GW")),
    +    hjust = -.2,
    +    family = "IBM Plex Mono"
    +  ) +
    +  scale_y_continuous(expand = expansion(c(.1, .4))) +
    +  coord_flip() +
    +  theme_void() +
    +  transition_states(Year)
    +
    +animate(capacity_anim, res = 300, width = 1000, height = 100, nframes = 100)
    +
    +
    +library(magick)
    +
    +map_gif <- image_read("turbine_map.gif")
    +bar_gif <- image_read("capacity_bar.gif")
    +
    +new_gif <- image_append(c(map_gif[1], bar_gif[1]), stack = TRUE)
    +
    +for(i in 2:100){
    +  combined <- image_append(c(map_gif[i], bar_gif[i]), stack = TRUE)
    +  new_gif <- c(new_gif, combined)
    +}
    +
    +new_gif
    +
    +
    +
    +
    +
    +
    +
      +
    1. If I don’t count all the convenient US-centric data/packages I’ve used to plot American maps before, this would be the first map I’ve made from scratch.↩︎

    2. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-10-28-tidytuesday-2020-week-44/preview.png b/docs/posts/2020-10-28-tidytuesday-2020-week-44/preview.png new file mode 100644 index 00000000..322de215 Binary files /dev/null and b/docs/posts/2020-10-28-tidytuesday-2020-week-44/preview.png differ diff --git a/docs/posts/2020-10-28-tidytuesday-2020-week-44/tidytuesday_2020_44.gif b/docs/posts/2020-10-28-tidytuesday-2020-week-44/tidytuesday_2020_44.gif new file mode 100644 index 00000000..d76d2b78 Binary files /dev/null and b/docs/posts/2020-10-28-tidytuesday-2020-week-44/tidytuesday_2020_44.gif differ diff --git a/docs/posts/2020-11-03-tidytuesday-2020-week-45/index.html b/docs/posts/2020-11-03-tidytuesday-2020-week-45/index.html new file mode 100644 index 00000000..f601f039 --- /dev/null +++ b/docs/posts/2020-11-03-tidytuesday-2020-week-45/index.html @@ -0,0 +1,2708 @@ + + + + + + + + + + + + + + + + + + + +June Choe: TidyTuesday 2020 week 45 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    TidyTuesday 2020 week 45

    + + + +

    Waffle chart of IKEA furnitures in stock

    +
    + + + +
    + +
    + +
    +

    Visualization

    +
    +

    +
    +

    Things I learned

    +
      +
    • How to make waffle charts with {waffle} (finally!)

    • +
    • Using {patchwork} for a large list of plots using wrap_plots() and theme styling inside plot_annotation()

    • +
    • Working with a long canvas using the cairo_pdf() device

    • +
    • Using {ggfittext} for dynamically re-sizing annotations.

    • +
    +

    Things to improve

    +
      +
    • Couldn’t figure out background color for the entire visual and white ended up looking a bit too harsh on the eye

    • +
    • Ideally would like to replace the squares with icons. Maybe I could’ve pursued that if I only plotted a couple furnitures.

    • +
    • The plot ended up being a bit too long. Again could’ve cut down a bit there, but I don’t mind it for this submission because I was more focused on learning how to make waffle charts at all.

    • +
    • Oops forgot to put in the data source

    • +
    +

    Code

    +

    Also available on github

    +
    +
    +
    library(tidyverse)
    +library(waffle)
    +library(extrafont)
    +library(patchwork)
    +
    +tuesdata <- tidytuesdayR::tt_load(2020, week = 45)
    +
    +ikea_counts <- tuesdata$ikea %>% 
    +  count(category) %>% 
    +  mutate(n = round(n/5)) %>% 
    +  arrange(-n)
    +
    +ikea_colors <- c(nord::nord_palettes$algoma_forest, dutchmasters::dutchmasters_pal()(13)[-c(1, 8, 12)])
    +
    +ikea_waffles <- map(1:nrow(ikea_counts), ~ {
    +  df <- slice(ikea_counts, .x)
    +  ggplot(df) +
    +    geom_waffle(
    +      aes(fill = category, values = n),
    +      n_rows = 20,
    +      size = 1.5,
    +      flip = TRUE,
    +      show.legend = FALSE
    +    ) +
    +    scale_fill_manual(values = ikea_colors[.x]) +
    +    ggfittext::geom_fit_text(
    +      aes(xmin = -15, xmax = -5, ymin = .5, ymax = .5 + ceiling(df$n/20), label = category),
    +      size = 54, grow = FALSE, fullheight = FALSE, place = "left" ,
    +      family = "Roboto Slab", fontface = "bold"
    +    ) +
    +    coord_equal(xlim = c(-16, 21)) +
    +    theme_void()
    +})
    +
    +legend_key <- ggplot() +
    +  annotation_custom(rectGrob(0.5, 0.5, height = .02, width = .02, gp = gpar(fill = "grey50", color = "black", lwd = 1))) +
    +  annotation_custom(textGrob("=  5 units", gp = gpar(fontfamily = "Roboto Slab", fontface = "bold", fontsize = 12)), 3, 2.6) +
    +  coord_equal(xlim = c(0, 5), ylim = c(0, 5)) +
    +  theme_void()
    +
    +patched <- wrap_plots(ikea_waffles, ncol = 1) +
    +  plot_annotation(
    +    title = "<span style='color:#997A00'>IKEA</span> <span style='color:#001F5C'>Furnitures in Stock</span>",
    +    caption = "@yjunechoe",
    +    theme = theme(
    +      plot.title = ggtext::element_markdown(
    +        size = 100,
    +        family = "Noto",
    +        face = "bold",
    +        hjust = .5,
    +        margin = margin(t = 1.5, b = 2, unit = "in")
    +      ),
    +      plot.caption = element_text(
    +        size = 32,
    +        family = "IBM Plex Mono",
    +        face = "bold",
    +        margin = margin(t = 1, b = 1, unit = "in")
    +      ),
    +      plot.margin = margin(2, 2, 2, 2, unit = "in")
    +    )
    +  ) &
    +  theme(plot.margin = margin(t = .5, b = .5, unit = "in")) 
    +
    +
    +ggsave("tidytuesday_2020_45.pdf", patched, device = cairo_pdf, scale = 2, width = 12, height = 26, limitsize = FALSE)
    +
    +
    +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview.png b/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview.png new file mode 100644 index 00000000..abce8cc2 Binary files /dev/null and b/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview.png differ diff --git a/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview_full.png b/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview_full.png new file mode 100644 index 00000000..86651ce6 Binary files /dev/null and b/docs/posts/2020-11-03-tidytuesday-2020-week-45/preview_full.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/biblio.bib b/docs/posts/2020-11-08-plot-makeover-2/biblio.bib new file mode 100644 index 00000000..6ef43792 --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/biblio.bib @@ -0,0 +1,6 @@ +@proceedings{Yurovsky2008MutualEI, + title={Mutual Exclusivity in Cross-Situational Statistical Learning}, + author={Daniel Yurovsky and C. Yu}, + year={2008}, + url="https://dll.sitehost.iu.edu/papers/Yurovsky_cs08.pdf" +} \ No newline at end of file diff --git a/docs/posts/2020-11-08-plot-makeover-2/index.html b/docs/posts/2020-11-08-plot-makeover-2/index.html new file mode 100644 index 00000000..f6f70451 --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/index.html @@ -0,0 +1,2862 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Plot Makeover #2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Plot Makeover #2

    + + + +

    Making a dodged-stacked hybrid bar plot in {ggplot2}

    +
    + + + +
    +
    + +
    +
    + +
    +

    This is the second installment of plot makeover where I take a plot in the wild and make very opinionated modifications to it.

    +

    Before

    +

    Our plot-in-the-wild comes from (Yurovsky and Yu 2008), a paper on statistical word learning. The plot that I’ll be looking at here is Figure 2, a bar plot of accuracy in a 3-by-3 experimental design.

    +
    +
    +Plot from Yurovsky and Yu (2008) +

    +Figure 1: Plot from Yurovsky and Yu (2008) +

    +
    +
    +

    As you might notice, there’s something interesting going on in this bar plot. It looks like the red and green bars stack together but dodge from the blue bar. It’s looks a bit weird for me as someone who mainly uses {ggplot2} because this kind of a hybrid design is not explicitly supported in the API.

    +

    For this plot makeover, I’ll leave aside the issue of whether having a half-stacked, half-dodged bar plot is a good idea.1 In fact, I’m not even gonna focus much on the “makeover” part. Instead I’m just going to take a shot at recreating this plot (likely made in MATLAB with post-processing in PowerPoint) in {ggplot2}.

    +

    My Plan

    +

    Again, my primary goal here is replication. But I do want to touch up on some aesthetics while I’m at it.

    +

    Major Changes:

    +
      +
    • Move the title to above the plot

    • +
    • Move the legend inside the plot

    • +
    • Move/remove the y-axis title so it’s not vertically aligned

    • +
    +

    Minor Changes:

    +
      +
    • Remove grid lines

    • +
    • Put y-axis in percentages

    • +
    • Add white borders around the bars for clearer color contrast

    • +
    +

    After

    +

    First draft

    +

    For a first pass on the makeover, I wanted to get the hybrid design right.

    +

    The plot below isn’t quite there in terms of covering everything I laid out in my plan, but it does replicate the bar plot design specifically.

    +
    +
    +

    Plot

    +
    +

    +
    +
    +
    +

    Code

    +
    +
    +
    library(tidyverse)
    +library(extrafont)
    +
    +df <- tribble(
    +  ~Condition, ~Referent, ~Accuracy,
    +  "Primacy",  "Single",  0.63,
    +  "Primacy",  "Primacy", 0.59,
    +  "Recency",  "Single",  0.63,
    +  "Recency",  "Recency", 0.5,
    +  "Both",     "Single",  0.63,
    +  "Both",     "Primacy", 0.5,
    +  "Both",     "Recency", 0.31
    +) %>% 
    +  mutate(
    +    error_low = runif(7, .04, .06),
    +    error_high = runif(7, .04, .06),
    +    Condition_name = factor(Condition, levels = c("Primacy", "Recency", "Both")),
    +    Condition = as.numeric(Condition_name),
    +    Referent = factor(Referent, levels = c("Single", "Recency", "Primacy")),
    +    left = Referent == "Single",
    +    color = case_when(
    +      Referent == "Single" ~ "#29476B",
    +      Referent == "Primacy" ~ "#AD403D",
    +      Referent == "Recency" ~ "#9BBB58"
    +    )
    +  )
    +
    +
    +ggplot(mapping = aes(x = Condition, y = Accuracy, fill = color)) +
    +  geom_col(
    +    data = filter(df, left),
    +    width = .3,
    +    color = "white",
    +    position = position_nudge(x = -.3)
    +  ) +
    +  geom_errorbar(
    +    aes(ymin = Accuracy - error_low, ymax = Accuracy + error_high),
    +    data = filter(df, left),
    +    width = .1,
    +    position = position_nudge(x = -.3)
    +  ) +
    +  geom_col(
    +    data = filter(df, !left),
    +    color = "white",
    +    width = .3,
    +  ) +
    +  geom_errorbar(
    +    aes(y = y, ymin = y - error_low, ymax = y + error_high),
    +    data = filter(df, !left) %>% 
    +      group_by(Condition) %>% 
    +      mutate(y = accumulate(Accuracy, sum)),
    +    width = .1
    +  ) +
    +  scale_fill_identity(
    +    labels = levels(df$Referent),
    +    guide = guide_legend(title = "Referent")
    +  ) +
    +  scale_x_continuous(
    +    breaks = 1:3 - .15,
    +    labels = levels(df$Condition_name),
    +    expand = expansion(.1)
    +  ) +
    +  scale_y_continuous(
    +    breaks = scales::pretty_breaks(6),
    +    labels = str_remove(scales::pretty_breaks(6)(0:1), "\\.0+"),
    +    limits = 0:1,
    +    expand = expansion(0)
    +  ) +
    +  labs(
    +    title = "Exp1: Accuracy by Condition and Word Type"
    +  ) +
    +  theme_classic(
    +    base_family = "Roboto",
    +    base_size = 16
    +  )
    +
    +
    +
    +
    +
    +

    As you might guess from my two calls to geom_col() and geom_errorbar(), I actually split the plotting of the bars into two parts. First I drew the blue bars and their errorbars, then I drew the green and red bars and their errorbars.

    +

    Effectively, the above plot is a combination of these two:2

    +
    +

    +
    +

    A bit hacky, I guess, but it works!

    +

    +

    +

    +

    +

    Final touch-up

    +
    +

    +
    +
    +
    +
    ggplot(mapping = aes(x = Condition, y = Accuracy, fill = color)) +
    +  geom_col(
    +    data = filter(df, left),
    +    width = .3,
    +    color = "white",
    +    position = position_nudge(x = -.3),
    +  ) +
    +  geom_errorbar(
    +    aes(ymin = Accuracy - error_low, ymax = Accuracy + error_high),
    +    data = filter(df, left),
    +    width = .1,
    +    position = position_nudge(x = -.3)
    +  ) +
    +  geom_col(
    +    data = filter(df, !left),
    +    color = "white",
    +    width = .3, 
    +  ) +
    +  geom_errorbar(
    +    aes(y = y, ymin = y - error_low, ymax = y + error_high),
    +    data = filter(df, !left) %>% 
    +      group_by(Condition) %>% 
    +      mutate(y = accumulate(Accuracy, sum)),
    +    width = .1
    +  ) +
    +  geom_hline(
    +    aes(yintercept = .25),
    +    linetype = 2,
    +    size = 1,
    +  ) +
    +  geom_text(
    +    aes(x = 3.4, y = .29),
    +    label = "Chance",
    +    family = "Adelle",
    +    color = "grey20",
    +    inherit.aes = FALSE
    +  ) +
    +  scale_fill_identity(
    +    labels = c("Single", "Primacy", "Recency"),
    +    guide = guide_legend(
    +      title = NULL,
    +      direction = "horizontal",
    +      override.aes = list(fill = c("#29476B", "#AD403D", "#9BBB58"))
    +    )
    +  ) +
    +  scale_x_continuous(
    +    breaks = 1:3 - .15,
    +    labels = levels(df$Condition_name),
    +    expand = expansion(c(.1, .05))
    +  ) +
    +  scale_y_continuous(
    +    breaks = scales::pretty_breaks(6),
    +    labels = scales::percent_format(1),
    +    limits = 0:1,
    +    expand = expansion(0)
    +  ) +
    +  labs(
    +    title = "Accuracy by Condition and Referent",
    +    y = NULL
    +  ) +
    +  theme_classic(
    +    base_family = "Roboto",
    +    base_size = 16
    +  ) +
    +  theme(
    +    plot.title.position = "plot",
    +    plot.title = element_text(
    +      family = "Roboto Slab",
    +      margin = margin(0, 0, 1, 0, "cm")
    +    ),
    +    legend.position = c(.35, .9),
    +    axis.title.x = element_text(margin = margin(t = .4, unit = "cm")),
    +    plot.margin = margin(1, 1, .7, 1, "cm")
    +  )
    +
    +
    +
    +
    +
    +
    +Yurovsky, Daniel, and C. Yu. 2008. Mutual Exclusivity in Cross-Situational Statistical Learning. https://dll.sitehost.iu.edu/papers/Yurovsky_cs08.pdf. +
    +
    +
    +
    +
      +
    1. I actually don’t even have a strong feeling about this. It does look kinda cool.↩︎

    2. +
    3. I used a neat trick from the R Markdown Cookbook to get the plots printed side-by-side↩︎

    4. +
    +
    + + + +
    + +
    +
    + + + + + +
    +

    References

    +
    +
    + + + + + + + + + + + diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/final-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/final-1.png new file mode 100644 index 00000000..28167f76 Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/final-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/first-draft-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/first-draft-1.png new file mode 100644 index 00000000..4657026b Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/first-draft-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-1-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-1-1.png new file mode 100644 index 00000000..b473b5fa Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-1-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-1.png new file mode 100644 index 00000000..7d7aa25e Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-2.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-2.png new file mode 100644 index 00000000..c6d602a5 Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-2-2.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-1.png new file mode 100644 index 00000000..d1f87e93 Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-2.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-2.png new file mode 100644 index 00000000..0deceb09 Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-3-2.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-1.png new file mode 100644 index 00000000..963d6eed Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-2.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-2.png new file mode 100644 index 00000000..f10c5523 Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-4-2.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..dd21d95d Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..a247e42c Binary files /dev/null and b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.5/header-attrs.js b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.6/header-attrs.js b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.6/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/header-attrs-2.6/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.css b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.css new file mode 100644 index 00000000..e3b3a00a --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.css @@ -0,0 +1,104 @@ +/* prefixed by https://autoprefixer.github.io (PostCSS: v7.0.23, autoprefixer: v9.7.3) */ + +.panelset { + width: 100%; + position: relative; + --panel-tabs-border-bottom: #ddd; + --panel-tab-foreground: currentColor; + --panel-tab-background: unset; + --panel-tab-active-foreground: currentColor; + --panel-tab-active-background: unset; + --panel-tab-hover-foreground: currentColor; + --panel-tab-hover-background: unset; + --panel-tab-active-border-color: currentColor; + --panel-tab-hover-border-color: currentColor; + --panel-tab-inactive-opacity: 0.5; + --panel-tab-font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; +} + +.panelset * { + box-sizing: border-box; +} + +.panelset .panel-tabs { + display: -webkit-box; + display: flex; + flex-wrap: wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + flex-direction: row; + -webkit-box-pack: start; + justify-content: start; + -webkit-box-align: center; + align-items: center; + overflow-y: visible; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding: 0 0 2px 0; + box-shadow: inset 0 -2px 0px var(--panel-tabs-border-bottom); +} + +.panelset .panel-tabs * { + -webkit-transition: opacity 0.5s ease; + transition: opacity 0.5s ease; +} + +.panelset .panel-tabs .panel-tab { + min-height: 50px; + display: -webkit-box; + display: flex; + -webkit-box-pack: center; + justify-content: center; + -webkit-box-align: center; + align-items: center; + padding: 0.5em 1em; + font-family: var(--panel-tab-font-family); + opacity: var(--panel-tab-inactive-opacity); + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + color: var(--panel-tab-foreground); + background-color: var(--panel-tab-background); + list-style: none; + z-index: 5; +} + +.panelset .panel-tabs .panel-tab > a { + color: currentColor; + text-decoration: none; +} + +.panelset .panel-tabs .panel-tab > a:focus { + outline: none; +} + +.panelset .panel-tabs .panel-tab:hover { + border-bottom-color: var(--panel-tab-hover-border-color); + color: var(--panel-tab-hover-foreground); + background-color: var(--panel-tab-hover-background); + opacity: 1; + cursor: pointer; + z-index: 10; +} + +.panelset .panel-tabs .panel-tab:focus { + outline: none; + color: var(--panel-tab-hover-foreground); + border-bottom-color: var(--panel-tab-hover-border-color); + background-color: var(--panel-tab-hover-background); +} + +.panelset .panel-tabs .panel-tab.panel-tab-active { + border-top-color: var(--panel-tab-active-border-color); + color: var(--panel-tab-active-foreground); + background-color: var(--panel-tab-active-background); + opacity: 1; +} + +.panelset .panel { + display: none; +} + +.panelset .panel-active { + display: block; +} diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.js b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.js new file mode 100644 index 00000000..6cda4336 --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/panelset-0.2.3/panelset.js @@ -0,0 +1,321 @@ +/* global slideshow */ +(function () { + const ready = function (fn) { + /* MIT License Copyright (c) 2016 Nuclei */ + /* https://github.com/nuclei/readyjs */ + const completed = () => { + document.removeEventListener('DOMContentLoaded', completed) + window.removeEventListener('load', completed) + fn() + } + if (document.readyState !== 'loading') { + setTimeout(fn) + } else { + document.addEventListener('DOMContentLoaded', completed) + window.addEventListener('load', completed) + } + } + + ready(function () { + [...document.querySelectorAll('.panel-name')] + .map(el => el.textContent.trim()) + + const panelIds = {} + + const uniquePanelId = (name) => { + name = encodeURIComponent(name.toLowerCase().replace(/[\s]/g, '-')) + if (Object.keys(panelIds).includes(name)) { + name += ++panelIds[name] + } else { + panelIds[name] = 1 + } + return name + } + + const identifyPanelName = (item) => { + let name = 'Panel' + + // If the item doesn't have a parent element, then we've already processed + // it, probably because we're in an Rmd, and it's been removed from the DOM + if (!item.parentElement) { + return + } + + // In R Markdown when header-attrs.js is present, we may have found a + // section header but the class attributes won't be duplicated on the tag + if ( + (item.tagName === 'SECTION' || item.classList.contains('section')) && + /^H[1-6]/.test(item.children[0].tagName) + ) { + name = item.children[0].textContent + item.classList.remove('panel-name') + item.removeChild(item.children[0]) + return name + } + + const nameDiv = item.querySelector('.panel-name') + if (!nameDiv) return name + + // In remarkjs the .panel-name span might be in a paragraph tag + // and if the

    is empty, we'll remove it + if ( + nameDiv.tagName === 'SPAN' && + nameDiv.parentNode.tagName === 'P' && + nameDiv.textContent === nameDiv.parentNode.textContent + ) { + name = nameDiv.textContent + item.removeChild(nameDiv.parentNode) + return name + } + + // If none of the above, remove the nameDiv and return the name + name = nameDiv.textContent + nameDiv.parentNode.removeChild(nameDiv) + return name + } + + const processPanelItem = (item) => { + const name = identifyPanelName(item) + if (!name) { + return null + } + return { name, content: item.children, id: uniquePanelId(name) } + } + + const getCurrentPanelFromUrl = (panelset) => { + const params = new URLSearchParams(window.location.search) + return params.get(panelset) + } + + const reflowPanelSet = (panels, idx) => { + const res = document.createElement('div') + res.className = 'panelset' + res.id = 'panelset' + (idx > 0 ? idx : '') + const panelSelected = getCurrentPanelFromUrl(res.id) + + // create header row + const headerRow = document.createElement('ul') + headerRow.className = 'panel-tabs' + headerRow.setAttribute('role', 'tablist') + panels + .map((p, idx) => { + const panelHeaderItem = document.createElement('li') + panelHeaderItem.className = 'panel-tab' + panelHeaderItem.setAttribute('role', 'tab') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + if (thisPanelIsActive) { + panelHeaderItem.classList.add('panel-tab-active') + panelHeaderItem.setAttribute('aria-selected', true) + } + panelHeaderItem.tabIndex = 0 + panelHeaderItem.id = res.id + '_' + p.id // #panelsetid_panelid + + const panelHeaderLink = document.createElement('a') + panelHeaderLink.href = '?' + res.id + '=' + p.id + '#' + panelHeaderItem.id + panelHeaderLink.setAttribute('onclick', 'return false;') + panelHeaderLink.tabIndex = -1 // list item is tabable, not link + panelHeaderLink.innerHTML = p.name + panelHeaderLink.setAttribute('aria-controls', p.id) + + panelHeaderItem.appendChild(panelHeaderLink) + return panelHeaderItem + }) + .forEach(el => headerRow.appendChild(el)) + + res.appendChild(headerRow) + + panels + .map((p, idx) => { + const panelContent = document.createElement('section') + panelContent.className = 'panel' + panelContent.setAttribute('role', 'tabpanel') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + panelContent.classList.toggle('panel-active', thisPanelIsActive) + panelContent.id = p.id + panelContent.setAttribute('aria-labelledby', p.id) + Array.from(p.content).forEach(el => panelContent.appendChild(el)) + return panelContent + }) + .forEach(el => res.appendChild(el)) + + return res + } + + /* + * Update selected panel for panelset or delete panelset from query string + * + * @param panelset Panelset ID to update in the search params + * @param panel Panel ID of selected panel in panelset, or null to delete from search params + * @param params Current params object, or params from window.location.search + */ + function updateSearchParams (panelset, panel, params = new URLSearchParams(window.location.search)) { + if (panel) { + params.set(panelset, panel) + } else { + params.delete(panelset) + } + return params + } + + /* + * Update the URL to match params + */ + const updateUrl = (params) => { + if (typeof params === 'undefined') return + params = params.toString() ? ('?' + params.toString()) : '' + const { pathname, hash } = window.location + const uri = pathname + params + hash + window.history.replaceState(uri, '', uri) + } + + const togglePanel = (clicked) => { + if (clicked.nodeName.toUpperCase() === 'A') { + clicked = clicked.parentElement + } + if (!clicked.classList.contains('panel-tab')) return + if (clicked.classList.contains('panel-tab-active')) return + + const tabs = clicked.parentNode + .querySelectorAll('.panel-tab') + const panels = clicked.parentNode.parentNode + .querySelectorAll('.panel') + const panelTabClicked = clicked.children[0].getAttribute('aria-controls') + const panelClicked = clicked.parentNode.parentNode.id + + Array.from(tabs) + .forEach(t => { + t.classList.remove('panel-tab-active') + t.removeAttribute('aria-selected') + }) + Array.from(panels) + .forEach(p => { + const active = p.id === panelTabClicked + p.classList.toggle('panel-active', active) + // make inactive panels inaccessible by keyboard navigation + if (active) { + p.removeAttribute('tabIndex') + p.removeAttribute('aria-hidden') + } else { + p.setAttribute('tabIndex', -1) + p.setAttribute('aria-hidden', true) + } + }) + + clicked.classList.add('panel-tab-active') + clicked.setAttribute('aria-selected', true) + + // update query string + const params = updateSearchParams(panelClicked, panelTabClicked) + updateUrl(params) + } + + const initPanelSet = (panelset, idx) => { + let panels = Array.from(panelset.querySelectorAll('.panel')) + if (!panels.length && panelset.matches('.section[class*="level"]')) { + // we're in tabset-alike R Markdown + const panelsetLevel = [...panelset.classList] + .filter(s => s.match(/^level/))[0] + .replace('level', '') + + // move children that aren't inside a section up above the panelset + Array.from(panelset.children).forEach(function (el) { + if (el.matches('div.section[class*="level"]')) return + panelset.parentElement.insertBefore(el, panelset) + }) + + // panels are all .sections with .level + const panelLevel = +panelsetLevel + 1 + panels = Array.from(panelset.querySelectorAll(`.section.level${panelLevel}`)) + } + + if (!panels.length) return + + const contents = panels.map(processPanelItem).filter(o => o !== null) + const newPanelSet = reflowPanelSet(contents, idx) + panelset.parentNode.insertBefore(newPanelSet, panelset) + panelset.parentNode.removeChild(panelset) + + // click and touch events + const panelTabs = newPanelSet.querySelector('.panel-tabs'); + ['click', 'touchend'].forEach(eventType => { + panelTabs.addEventListener(eventType, function (ev) { + togglePanel(ev.target) + ev.stopPropagation() + }) + }) + panelTabs.addEventListener('touchmove', function (ev) { + ev.preventDefault() + }) + + // key events + newPanelSet + .querySelector('.panel-tabs') + .addEventListener('keydown', (ev) => { + const self = ev.currentTarget.querySelector('.panel-tab-active') + if (ev.code === 'Space' || ev.code === 'Enter') { + togglePanel(ev.target) + ev.stopPropagation() + } else if (ev.code === 'ArrowLeft' && self.previousSibling) { + togglePanel(self.previousSibling) + self.previousSibling.focus() + ev.stopPropagation() + } else if (ev.code === 'ArrowRight' && self.nextSibling) { + togglePanel(self.nextSibling) + self.nextSibling.focus() + ev.stopPropagation() + } + }) + + return panels + } + + // initialize panels + Array.from(document.querySelectorAll('.panelset')).map(initPanelSet) + + if (typeof slideshow !== 'undefined') { + const getVisibleActivePanelInfo = () => { + const slidePanels = document.querySelectorAll('.remark-visible .panel-tab-active') + + if (!slidePanels.length) return null + + return slidePanels.map(panel => { + return { + panel, + panelId: panel.children[0].getAttribute('aria-controls'), + panelSetId: panel.parentNode.parentNode.id + } + }) + } + + slideshow.on('hideSlide', slide => { + // clear focus if we had a panel-tab selected + document.activeElement.blur() + + // clear search query for panelsets in current slide + const params = [...document.querySelectorAll('.remark-visible .panelset')] + .reduce(function (params, panelset) { + return updateSearchParams(panelset.id, null, params) + }, new URLSearchParams(window.location.search)) + + updateUrl(params) + }) + + slideshow.on('afterShowSlide', slide => { + const slidePanels = getVisibleActivePanelInfo() + + if (slidePanels) { + // only first panel gets focus + slidePanels[0].panel.focus() + // but still update the url to reflect all active panels + const params = slidePanels.reduce( + function (params, { panelId, panelSetId }) { + return updateSearchParams(panelSetId, panelId, params) + }, + new URLSearchParams(window.location.search) + ) + updateUrl(params) + } + }) + } + }) +})() diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.css b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.css new file mode 100644 index 00000000..2a38a374 --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.css @@ -0,0 +1,23 @@ +.xaringanextra-clipboard-button { + position: absolute; + top: 0; + right: 0; + font-size: 0.8em; + padding: 0.5em; + display: none; + background-color: transparent; + border: none; + opacity: 0.5; + border-radius: 0; +} + +.xaringanextra-clipboard-button:hover { + background-color: rgba(0, 0, 0, 0.1); + border: none; + opacity: 1; +} + +:hover > .xaringanextra-clipboard-button { + display: block; + transform: translateY(0); +} diff --git a/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.js b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.js new file mode 100644 index 00000000..05328185 --- /dev/null +++ b/docs/posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/xaringanExtra-clipboard-0.2.3/xaringanExtra-clipboard.js @@ -0,0 +1,98 @@ +/* global slideshow,window,document */ +window.xaringanExtraClipboard = function (selector, text) { + if (!window.ClipboardJS.isSupported()) return + if (!window.xaringanExtraClipboards) window.xaringanExtraClipboards = {} + + const ready = function (fn) { + /* MIT License Copyright (c) 2016 Nuclei */ + /* https://github.com/nuclei/readyjs */ + const completed = () => { + document.removeEventListener('DOMContentLoaded', completed) + window.removeEventListener('load', completed) + fn() + } + if (document.readyState !== 'loading') { + setTimeout(fn) + } else { + document.addEventListener('DOMContentLoaded', completed) + window.addEventListener('load', completed) + } + } + + ready(function () { + const { + button: buttonText = 'Copy Code', + success: successText = 'Copied!', + error: errorText = 'Press Ctrl+C to Copy' + } = text + + const template = '` + + const isRemarkSlideshow = typeof slideshow !== 'undefined' && + Object.prototype.hasOwnProperty.call(slideshow, 'getSlides') + + let siblingSelector = selector || 'pre' + if (!selector && isRemarkSlideshow) { + siblingSelector = '.remark-slides-area ' + siblingSelector + } + + // insert +

    +
    + + + + + + + + + + + + + +
    + + + + + + +
    +

    Collapse repetitive piping with reduce()

    + + + +

    Featuring accumulate()

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    12-13-2020 +
    + +
    + +
    + +
    +
    + +
    +

    Introduction

    +

    Happy pipes

    +

    Modern day programming with R is all about pipes.1 You start out with some object that undergoes incremental changes as it is passed (piped) into a chain of functions and finally returned as the desired output, like in this simple example. 2

    +
    +
    +
    set.seed(2021) # Can 2020 be over already?
    +
    +square <- function(x) x^2
    +deviation <- function(x) x - mean(x)
    +
    +nums <- runif(100)
    +
    +nums %>%
    +  deviation() %>%
    +  square() %>%
    +  mean() %>%
    +  sqrt()
    +
    +
    +
      [1] 0.3039881
    +
    +

    When we pipe (or pass anything through any function, for that matter), we often do one distinct thing at a time, like in the above example.

    +

    So, we rarely have a chain of functions that look like this:

    +
    +
    +
    library(dplyr)
    +
    +mtcars %>% 
    +  mutate(kmpg = mpg/1.6) %>% 
    +  mutate(disp = round(disp)) %>% 
    +  select(-vs) %>% 
    +  select(-am) %>% 
    +  select(-gear) %>% 
    +  select(-carb) %>% 
    +  filter(mpg > 15) %>% 
    +  filter(cyl == 6) %>% 
    +  filter(wt < 3)
    +
    +
    +
    +

    … because many functions are vectorized, or designed to handle multiple values by other means, like this:

    +
    +
    +
    penguins %>% 
    +  mutate(kmpg = mpg/1.6, disp = round(disp)) %>% 
    +  select(-(vs:carb)) %>% 
    +  filter(mpg > 15, cyl == 6, wt < 3)
    +
    +
    +
    +

    Sad (repetitive) pipes

    +

    But some functions do not handle multiple inputs the way we want it to, or just not at all. Here are some examples of what I’m talking about.

    +

    In {ggplot2}, this doesn’t plot 3 overlapping points with sizes 8, 4, and 2:

    +
    +
    +
    library(ggplot2)
    +
    +ggplot(mtcars, aes(hp, mpg)) + 
    +  geom_point(size = c(8, 4, 2), alpha = .5)
    +
    +
    +
      Error: Aesthetics must be either length 1 or the same as the data (32): size
    +
    +

    So you have to do this:

    +
    +
    +
    ggplot(mtcars, aes(hp, mpg)) + 
    +  geom_point(size = 8, alpha = .5) +
    +  geom_point(size = 4, alpha = .5) +
    +  geom_point(size = 2, alpha = .5)
    +
    +
    +

    +
    +

    In {kableExtra}, this doesn’t color the third column “skyblue”, the fourth column “forestgreen”, and the fifth column “chocolate”:3

    +
    +
    +
    library(kableExtra)
    +
    +mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>% 
    +  column_spec(3:5, background = c("skyblue", "forestgreen", "chocolate"))
    +
    +
    +
      Warning in ensure_len_html(background, nrows, "background"): The number of
    +  provided values in background does not equal to the number of rows.
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +mpg + +cyl + +disp + +hp + +drat + +wt + +qsec + +vs + +am + +gear + +carb +
    +Mazda RX4 + +21.0 + +6 + +160 + +110 + +3.90 + +2.620 + +16.46 + +0 + +1 + +4 + +4 +
    +Mazda RX4 Wag + +21.0 + +6 + +160 + +110 + +3.90 + +2.875 + +17.02 + +0 + +1 + +4 + +4 +
    +Datsun 710 + +22.8 + +4 + +108 + +93 + +3.85 + +2.320 + +18.61 + +1 + +1 + +4 + +1 +
    +Hornet 4 Drive + +21.4 + +6 + +258 + +110 + +3.08 + +3.215 + +19.44 + +1 + +0 + +3 + +1 +
    +Hornet Sportabout + +18.7 + +8 + +360 + +175 + +3.15 + +3.440 + +17.02 + +0 + +0 + +3 + +2 +
    +Valiant + +18.1 + +6 + +225 + +105 + +2.76 + +3.460 + +20.22 + +1 + +0 + +3 + +1 +
    +
    +

    So you have to do this:

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>% 
    +  column_spec(3, background = "skyblue") %>% 
    +  column_spec(4, background = "forestgreen") %>% 
    +  column_spec(5, background = "chocolate")
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +mpg + +cyl + +disp + +hp + +drat + +wt + +qsec + +vs + +am + +gear + +carb +
    +Mazda RX4 + +21.0 + +6 + +160 + +110 + +3.90 + +2.620 + +16.46 + +0 + +1 + +4 + +4 +
    +Mazda RX4 Wag + +21.0 + +6 + +160 + +110 + +3.90 + +2.875 + +17.02 + +0 + +1 + +4 + +4 +
    +Datsun 710 + +22.8 + +4 + +108 + +93 + +3.85 + +2.320 + +18.61 + +1 + +1 + +4 + +1 +
    +Hornet 4 Drive + +21.4 + +6 + +258 + +110 + +3.08 + +3.215 + +19.44 + +1 + +0 + +3 + +1 +
    +Hornet Sportabout + +18.7 + +8 + +360 + +175 + +3.15 + +3.440 + +17.02 + +0 + +0 + +3 + +2 +
    +Valiant + +18.1 + +6 + +225 + +105 + +2.76 + +3.460 + +20.22 + +1 + +0 + +3 + +1 +
    +
    +

    In {dplyr}, this doesn’t make 3 new columns named “a”, “b”, and “c”, all filled with NA:4

    +
    +
    +
    new_cols <- c("a", "b", "c")
    +
    +mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  mutate(!!new_cols := NA)
    +
    +
    +
      Error: The LHS of `:=` must be a string or a symbol
    +
    +

    So you have to do either one of these:5

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  mutate(
    +    !!new_cols[1] := NA,
    +    !!new_cols[2] := NA,
    +    !!new_cols[3] := NA
    +  )
    +
    +mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  mutate(!!new_cols[1] := NA) %>% 
    +  mutate(!!new_cols[2] := NA) %>% 
    +  mutate(!!new_cols[3] := NA)
    +
    +
    +
    +
    +
         mpg  a  b  c
    +  1 21.0 NA NA NA
    +  2 21.0 NA NA NA
    +  3 22.8 NA NA NA
    +  4 21.4 NA NA NA
    +  5 18.7 NA NA NA
    +  6 18.1 NA NA NA
    +
    +

    So we’ve got functions being repeated, but in all these cases it looks like we can’t just throw in a vector and expect the function to loop/map over them internally in the specific way that we want it to. And the “correct ways” I provided here are not very satisfying: that’s a lot of copying and pasting!

    +

    Personally, I think it’d be nice to collapse these repetitive calls - but how?

    +

    Introducing purrr::reduce()

    +

    The reduce() function from the {purrr} package is a powerful functional that allows you to abstract away from a sequence of functions that are applied in a fixed direction. You should go give Advanced R Ch. 9.5 a read if you want an in-depth explanation, but here I’m just gonna give a quick crash course for our application of it to our current problem.6

    +

    All you need to know here is that reduce() takes a vector as its first argument, a function as its second argument, and an optional .init argument.7

    +

    Here’s a schematic:

    +
    +
    +From <a href='https://adv-r.hadley.nz/functionals.html'>Advanced R by Hadley Wickham</a> +

    +Figure 1: From Advanced R by Hadley Wickham +

    +
    +
    +

    Let me really quickly demonstrate reduce() in action.

    +

    Say you wanted to add up the numbers 1 through 5, but only using the plus operator +. You could do something like this:8

    +
    +
    +
    1 + 2 + 3 + 4 + 5
    +
    +
    +
      [1] 15
    +
    +

    Which is the same as this:

    +
    +
    +
    library(purrr)
    +reduce(1:5, `+`)
    +
    +
    +
      [1] 15
    +
    +

    And if you want the start value to be something that’s not the first argument of the vector, pass that to the .init argument:

    +
    +
    +
    identical(
    +  0.5 + 1 + 2 + 3 + 4 + 5,
    +  reduce(1:5, `+`, .init = 0.5)
    +)
    +
    +
    +
      [1] TRUE
    +
    +

    If you want to be specific, you can use an {rlang}-style anonymous function where .x is the accumulated value being passed into the first argument fo the function and .y is the second argument of the function.9

    +
    +
    +
    identical(
    +  reduce(1:5, `+`, .init = 0.5),
    +  reduce(1:5, ~ .x + .y, .init = 0.5)
    +)
    +
    +
    +
      [1] TRUE
    +
    +

    And two more examples just to demonstrate that directionality matters:

    +
    +
    +
    identical(
    +  reduce(1:5, `^`, .init = 0.5),
    +  reduce(1:5, ~ .x ^ .y, .init = 0.5) # .x on left, .y on right
    +)
    +
    +
    +
      [1] TRUE
    +
    +
    identical(
    +  reduce(1:5, `^`, .init = 0.5),
    +  reduce(1:5, ~ .y ^ .x, .init = 0.5) # .y on left, .x on right
    +)
    +
    +
    +
      [1] FALSE
    +
    +

    That’s pretty much all you need to know - let’s jump right in!

    +

    Example 1: {ggplot2}

    +

    A reduce() solution

    +

    Recall that we had this sad code:

    +
    +
    +
    ggplot(mtcars, aes(hp, mpg)) + 
    +  geom_point(size = 8, alpha = .5) +
    +  geom_point(size = 4, alpha = .5) +
    +  geom_point(size = 2, alpha = .5)
    +
    +
    +
    +

    For illustrative purposes, I’m going to move the + “pipes” to the beginning of each line:

    +
    +
    +
    ggplot(mtcars, aes(hp, mpg))
    +  + geom_point(size = 8, alpha = .5)
    +  + geom_point(size = 4, alpha = .5)
    +  + geom_point(size = 2, alpha = .5)
    +
    +
    +
    +

    At this point, we see a clear pattern emerge line-by-line. We start with ggplot(mtcars, aes(hp, mpg)), which is kind of its own thing. Then we have three repetitions of + geom_point(size = X, alpha = .5) where the X varies between 8, 4, and 2. We also notice that the sequence of calls goes from left to right, as is the normal order of piping.

    +

    Now let’s translate these observations into reduce(). I’m bad with words so here’s a visual:

    +
    +

    +
    +

    Let’s go over what we did in our call to reduce() above:

    + +

    If you want to see the actual code run, here it is:

    +
    +
    +
    reduce(
    +  c(8, 4, 2),
    +  ~ .x + geom_point(size = .y, alpha = .5),
    +  .init = ggplot(mtcars, aes(hp, mpg))
    +)
    +
    +
    +

    +
    +

    Let’s dig in a bit more, this time with an example that looks prettier.

    +

    Suppose you want to collapse the repeated calls to geom_point() in this code:

    +
    +
    +
    viridis_colors <- viridis::viridis(10)
    +
    +mtcars %>% 
    +  ggplot(aes(hp, mpg)) +
    +  geom_point(size = 20, color = viridis_colors[10]) +
    +  geom_point(size = 18, color = viridis_colors[9]) +
    +  geom_point(size = 16, color = viridis_colors[8]) +
    +  geom_point(size = 14, color = viridis_colors[7]) +
    +  geom_point(size = 12, color = viridis_colors[6]) +
    +  geom_point(size = 10, color = viridis_colors[5]) +
    +  geom_point(size = 8, color = viridis_colors[4]) +
    +  geom_point(size = 6, color = viridis_colors[3]) +
    +  geom_point(size = 4, color = viridis_colors[2]) +
    +  geom_point(size = 2, color = viridis_colors[1]) +
    +  scale_x_discrete(expand = expansion(.2)) +
    +  scale_y_continuous(expand = expansion(.2)) +
    +  theme_void() +
    +  theme(panel.background = element_rect(fill = "grey20"))
    +
    +
    +

    +
    +

    You can do this with reduce() in a couple ways:10

    +
    +
    +

    Method 1

    +

    Method 1: Move all the “constant” parts to .init, since the order of these layers don’t matter.

    +
    +
    +
    reduce(
    +    10L:1L,
    +    ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),
    +    
    +    .init = mtcars %>% 
    +      ggplot(aes(hp, mpg)) +
    +      scale_x_discrete(expand = expansion(.2)) +
    +      scale_y_continuous(expand = expansion(.2)) +
    +      theme_void() +
    +      theme(panel.background = element_rect(fill = "grey20"))
    +    
    +)
    +
    +
    +
    +
    +
    +

    Method 2

    +

    Method 2: Use reduce() in place, with the help of the {magrittr} dot .

    +
    +
    +
    mtcars %>% 
    +  ggplot(aes(hp, mpg)) %>% 
    +  
    +  reduce(
    +    10L:1L,
    +    ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),
    +    .init = . #<- right here!
    +  ) +
    +  
    +  scale_x_discrete(expand = expansion(.2)) +
    +  scale_y_continuous(expand = expansion(.2)) +
    +  theme_void() +
    +  theme(panel.background = element_rect(fill = "grey20"))
    +
    +
    +
    +
    +
    +

    Method 3

    +

    Method 3: Move all the “constant” parts to the top, wrap it in parentheses, and pass the whole thing into .init using the {magrittr} dot .

    +
    +
    +
    (mtcars %>% 
    +  ggplot(aes(hp, mpg)) +
    +  scale_x_discrete(expand = expansion(.2)) +
    +  scale_y_continuous(expand = expansion(.2)) +
    +  theme_void() +
    +  theme(panel.background = element_rect(fill = "grey20"))) %>% 
    +  
    +  reduce(
    +    10L:1L,
    +    ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),
    +    .init = . #<- right here!
    +  )
    +
    +
    +
    +
    +
    +

    All in all, we see that reduce() allows us to write more succinct code!

    +

    An obvious advantage to this is that it is now really easy to make a single change that applies to all the repeated calls.

    +

    For example, if I want to make the radius of the points grow/shrink exponentially, I just need to modify the anonymous function in the second argument of reduce():

    +
    +
    +
    # Using Method 3
    +(mtcars %>% 
    +  ggplot(aes(hp, mpg)) +
    +  scale_x_discrete(expand = expansion(.2)) +
    +  scale_y_continuous(expand = expansion(.2)) +
    +  theme_void() +
    +  theme(panel.background = element_rect(fill = "grey20"))) %>% 
    +  reduce(
    +    10L:1L,
    +    ~ .x + geom_point(size = .y ^ 1.5, color = viridis_colors[.y]),  # exponential!
    +    .init = .
    +  )
    +
    +
    +

    +
    +

    Yay, we collapsed ten layers of geom_point()!

    +

    feat. accumulate()

    +

    There’s actually one more thing I want to show here, which is holding onto intermediate values using accumulate().

    +

    accumulate() is like reduce(), except instead of returning a single value which is the output of the very last function call, it keeps all intermediate values and returns them in a list.

    +
    +
    +
    accumulate(1:5, `+`)
    +
    +
    +
      [1]  1  3  6 10 15
    +
    +

    Check out what happens if I change reduce() to accumulate() and return each element of the resulting list:

    +
    +
    +
    plots <- (mtcars %>% 
    +  ggplot(aes(hp, mpg)) +
    +  scale_x_discrete(expand = expansion(.2)) +
    +  scale_y_continuous(expand = expansion(.2)) +
    +  theme_void() +
    +  theme(panel.background = element_rect(fill = "grey20"))) %>% 
    +  accumulate(
    +    10L:1L,
    +    ~ .x + geom_point(size = .y ^ 1.5, color = viridis_colors[.y]),
    +    .init = .
    +  )
    +
    +for (i in plots) { plot(i) }
    +
    +
    +

    +
    +

    We got back the intermediate plots!

    +

    Are you thinking what I’m thinking? Let’s animate this!

    +
    +
    +
    library(magick)
    +
    +# change ggplot2 objects into images
    +imgs <- map(1:length(plots), ~ {
    +  img <- image_graph(width = 672, height = 480)
    +  plot(plots[[.x]])
    +  dev.off()
    +  img
    +})
    +
    +# combine images as frames
    +imgs <- image_join(imgs)
    +
    +# animate
    +image_animate(imgs)
    +
    +
    +
    +
    +

    +
    +

    Neat!11

    +

    Example 2: {kableExtra}

    +

    A reduce2() solution

    +

    Recall that we had this sad code:

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>% 
    +  column_spec(3, background = "skyblue") %>% 
    +  column_spec(4, background = "forestgreen") %>% 
    +  column_spec(5, background = "chocolate")
    +
    +
    +
    +

    We’ve got two things varying here: the column location 3:5 and the background color c("skyblue", "forestgreen", "chocolate"). We could do the same trick I sneaked into the previous section by just passing one vector to reduce() that basically functions as an index:12

    +
    +
    +
    numbers <- 3:5
    +background_colors <- c("skyblue", "forestgreen", "chocolate")
    +
    +(mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto")) %>% 
    +  reduce(
    +    1:3,
    +    ~ .x %>% column_spec(numbers[.y], background = background_colors[.y]),
    +    .init = .
    +  )
    +
    +
    +
    +

    But I want to use this opportunity to showcase reduce2(), which explicitly takes a second varying argument to the function that you are reduce()-ing over.

    +

    Here, ..1 is like the .x and ..2 is like the .y from reduce(). The only new part is ..3 which refers to the second varying argument.

    +
    +
    +
    (mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto")) %>% 
    +  reduce2(
    +    3:5,                                           # 1st varying argument (represented by ..2)
    +    c("skyblue", "forestgreen", "chocolate"),      # 2nd varying argument (represented by ..3)
    +    ~ ..1 %>% column_spec(..2, background = ..3),
    +    .init = .
    +  )
    +
    +
    +
    +

    We’re not done yet! We can actually skip the {magrittr} pipe %>% and just stick ..1 as the first argument inside column_spec().13 This actually improves performance because you’re removing the overhead from evaluating the pipe!

    +

    Additionally, because the pipe forces evaluation with each call unlike + in {ggplot2}, we don’t need the parantheses wrapped around the top part of the code for the {magrittr} dot . to work!

    +

    Here is the final reduce2() solution for our sad code:

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>%       # No need to wrap in parentheses!
    +  reduce2(
    +    3:5,                                          
    +    c("skyblue", "forestgreen", "chocolate"),  
    +    ~ column_spec(..1, ..2, background = ..3),  # No need for the pipe!
    +    .init = .
    +  )
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +mpg + +cyl + +disp + +hp + +drat + +wt + +qsec + +vs + +am + +gear + +carb +
    +Mazda RX4 + +21.0 + +6 + +160 + +110 + +3.90 + +2.620 + +16.46 + +0 + +1 + +4 + +4 +
    +Mazda RX4 Wag + +21.0 + +6 + +160 + +110 + +3.90 + +2.875 + +17.02 + +0 + +1 + +4 + +4 +
    +Datsun 710 + +22.8 + +4 + +108 + +93 + +3.85 + +2.320 + +18.61 + +1 + +1 + +4 + +1 +
    +Hornet 4 Drive + +21.4 + +6 + +258 + +110 + +3.08 + +3.215 + +19.44 + +1 + +0 + +3 + +1 +
    +Hornet Sportabout + +18.7 + +8 + +360 + +175 + +3.15 + +3.440 + +17.02 + +0 + +0 + +3 + +2 +
    +Valiant + +18.1 + +6 + +225 + +105 + +2.76 + +3.460 + +20.22 + +1 + +0 + +3 + +1 +
    +
    +

    And of course, we now have the flexibilty to do much more complicated manipulations!

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>% 
    +  reduce2(
    +    1:12,                                          
    +    viridis::viridis(12),  
    +    ~ column_spec(..1, ..2, background = ..3, color = if(..2 < 5){"white"}),
    +    .init = .
    +  )
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +mpg + +cyl + +disp + +hp + +drat + +wt + +qsec + +vs + +am + +gear + +carb +
    +Mazda RX4 + +21.0 + +6 + +160 + +110 + +3.90 + +2.620 + +16.46 + +0 + +1 + +4 + +4 +
    +Mazda RX4 Wag + +21.0 + +6 + +160 + +110 + +3.90 + +2.875 + +17.02 + +0 + +1 + +4 + +4 +
    +Datsun 710 + +22.8 + +4 + +108 + +93 + +3.85 + +2.320 + +18.61 + +1 + +1 + +4 + +1 +
    +Hornet 4 Drive + +21.4 + +6 + +258 + +110 + +3.08 + +3.215 + +19.44 + +1 + +0 + +3 + +1 +
    +Hornet Sportabout + +18.7 + +8 + +360 + +175 + +3.15 + +3.440 + +17.02 + +0 + +0 + +3 + +2 +
    +Valiant + +18.1 + +6 + +225 + +105 + +2.76 + +3.460 + +20.22 + +1 + +0 + +3 + +1 +
    +
    +

    feat. accumulate2()

    +

    Yep, that’s right - more animations with accumulate() and {magick}!

    +

    Actually, to be precise, we’re going to use the accumuate2() here to replace our reduce2().

    +

    First, we save the list of intermediate outputs to tables:

    +
    +
    +
    tables <- mtcars %>% 
    +  head() %>% 
    +  kbl() %>% 
    +  kable_classic(html_font = "Roboto") %>% 
    +  kable_styling(full_width = FALSE) %>% # Added to keep aspect ratio constant when saving
    +  accumulate2(
    +    1:(length(mtcars)+1),                                          
    +    viridis::viridis(length(mtcars)+1),  
    +    ~ column_spec(..1, ..2, background = ..3, color = if(..2 < 5){"white"}),
    +    .init = .
    +  )
    +
    +
    +
    +

    Then, we save each table in tables as an image:

    +
    +
    +
    iwalk(tables, ~ save_kable(.x, file = here::here("img", paste0("table", .y, ".png")), zoom = 2))
    +
    +
    +
    +

    Finally, we read them in and animate:

    +
    +
    +
    tables <- map(
    +  paste0("table", 1:length(tables), ".png"),
    +  ~ image_read(here::here("img", .x))
    +)
    +
    +tables <- image_join(tables)
    +
    +image_animate(tables)
    +
    +
    +
    +
    +

    +
    +

    Bet you don’t see animated tables often!

    +

    Example 3: {dplyr}

    +

    A reduce() solution

    +

    Recall that we had this sad code:

    +
    +
    +
    new_cols <- c("a", "b", "c")
    +
    +mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  mutate(!!new_cols[1] := NA) %>% 
    +  mutate(!!new_cols[2] := NA) %>% 
    +  mutate(!!new_cols[3] := NA)
    +
    +
    +
         mpg  a  b  c
    +  1 21.0 NA NA NA
    +  2 21.0 NA NA NA
    +  3 22.8 NA NA NA
    +  4 21.4 NA NA NA
    +  5 18.7 NA NA NA
    +  6 18.1 NA NA NA
    +
    +

    You know the drill - a simple call to reduce() gives us three new columns with names corresponding to the elements of the new_cols character vector we defined above:

    +
    +
    +
    # Converting to tibble for nicer printing
    +mtcars <- as_tibble(mtcars)
    +
    +mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  reduce(
    +    new_cols,
    +    ~ mutate(.x, !!.y := NA),
    +    .init = .
    +  )
    +
    +
    +
      # A tibble: 6 x 4
    +      mpg a     b     c    
    +    <dbl> <lgl> <lgl> <lgl>
    +  1  21   NA    NA    NA   
    +  2  21   NA    NA    NA   
    +  3  22.8 NA    NA    NA   
    +  4  21.4 NA    NA    NA   
    +  5  18.7 NA    NA    NA   
    +  6  18.1 NA    NA    NA
    +
    +

    Again, this gives you a lot of flexibility, like the ability to dynamically assign values to each new column:

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  reduce(
    +    new_cols,
    +    ~ mutate(.x, !!.y := paste0(.y, "-", row_number())),
    +    .init = .
    +  )
    +
    +
    +
      # A tibble: 6 x 4
    +      mpg a     b     c    
    +    <dbl> <chr> <chr> <chr>
    +  1  21   a-1   b-1   c-1  
    +  2  21   a-2   b-2   c-2  
    +  3  22.8 a-3   b-3   c-3  
    +  4  21.4 a-4   b-4   c-4  
    +  5  18.7 a-5   b-5   c-5  
    +  6  18.1 a-6   b-6   c-6
    +
    +

    We can take this even further using context dependent expressions like cur_data(), and do something like keeping track of the columns present at each point a new column has been created via mutate():

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  reduce(
    +    new_cols,
    +    ~ mutate(.x, !!.y := paste(c(names(cur_data()), .y), collapse = "-")),
    +    .init = .
    +  )
    +
    +
    +
      # A tibble: 6 x 4
    +      mpg a     b       c        
    +    <dbl> <chr> <chr>   <chr>    
    +  1  21   mpg-a mpg-a-b mpg-a-b-c
    +  2  21   mpg-a mpg-a-b mpg-a-b-c
    +  3  22.8 mpg-a mpg-a-b mpg-a-b-c
    +  4  21.4 mpg-a mpg-a-b mpg-a-b-c
    +  5  18.7 mpg-a mpg-a-b mpg-a-b-c
    +  6  18.1 mpg-a mpg-a-b mpg-a-b-c
    +
    +

    Here’s another example just for fun - an “addition matrix”:14

    +
    +
    +
    mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  reduce(
    +    pull(., mpg),
    +    ~ mutate(.x, !!as.character(.y) := .y + mpg),
    +    .init = .
    +  )
    +
    +
    +
      # A tibble: 6 x 6
    +      mpg  `21` `22.8` `21.4` `18.7` `18.1`
    +    <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
    +  1  21    42     43.8   42.4   39.7   39.1
    +  2  21    42     43.8   42.4   39.7   39.1
    +  3  22.8  43.8   45.6   44.2   41.5   40.9
    +  4  21.4  42.4   44.2   42.8   40.1   39.5
    +  5  18.7  39.7   41.5   40.1   37.4   36.8
    +  6  18.1  39.1   40.9   39.5   36.8   36.2
    +
    +

    Let’s now look at a more practical application of this: explicit dummy coding!

    +

    In R, the factor data structure allows implicit dummy coding, which you can access using contrasts().

    +

    Here, in our data penguins from the {palmerpenguins} package, we see that the 3-way contrast between “Adelie”, “Chinstrap”, and “Gentoo” in the species factor column is treatment coded, with “Adelie” set as the reference level:

    +
    +
    +
    data("penguins", package = "palmerpenguins")
    +
    +penguins_implicit <- penguins %>% 
    +  na.omit() %>% 
    +  select(species, flipper_length_mm) %>% 
    +  mutate(species = factor(species))
    +
    +contrasts(penguins_implicit$species)
    +
    +
    +
                Chinstrap Gentoo
    +  Adelie            0      0
    +  Chinstrap         1      0
    +  Gentoo            0      1
    +
    +

    We can also infer that from the output of this simple linear model:15

    +
    +
    +
    broom::tidy(lm(flipper_length_mm ~ species, data = penguins_implicit))
    +
    +
    +
      # A tibble: 3 x 5
    +    term             estimate std.error statistic   p.value
    +    <chr>               <dbl>     <dbl>     <dbl>     <dbl>
    +  1 (Intercept)        190.       0.552    344.   0.       
    +  2 speciesChinstrap     5.72     0.980      5.84 1.25e-  8
    +  3 speciesGentoo       27.1      0.824     32.9  2.68e-106
    +
    +

    What’s cool is that you can make this 3-way treatment coding explicit by expanding the matrix into actual columns of the data!

    +

    Here’s a reduce() solution:

    +
    +
    +
    penguins_explicit <- 
    +  reduce(
    +    levels(penguins_implicit$species)[-1],
    +    ~ mutate(.x, !!paste0("species", .y) := as.integer(species == .y)),
    +    .init = penguins_implicit
    +  )
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +species + +flipper_length_mm + +speciesChinstrap + +speciesGentoo +
    +Adelie + +181 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +181 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +182 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +198 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +197 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +194 + +0 + +0 +
    +Adelie + +174 + +0 + +0 +
    +Adelie + +180 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +180 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +183 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +172 + +0 + +0 +
    +Adelie + +180 + +0 + +0 +
    +Adelie + +178 + +0 + +0 +
    +Adelie + +178 + +0 + +0 +
    +Adelie + +188 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +180 + +0 + +0 +
    +Adelie + +181 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +182 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +182 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +188 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +200 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +181 + +0 + +0 +
    +Adelie + +194 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +192 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +192 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +188 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +198 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +197 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +194 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +202 + +0 + +0 +
    +Adelie + +205 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +208 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +178 + +0 + +0 +
    +Adelie + +192 + +0 + +0 +
    +Adelie + +192 + +0 + +0 +
    +Adelie + +203 + +0 + +0 +
    +Adelie + +183 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +199 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +181 + +0 + +0 +
    +Adelie + +197 + +0 + +0 +
    +Adelie + +198 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +197 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +196 + +0 + +0 +
    +Adelie + +188 + +0 + +0 +
    +Adelie + +199 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +189 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +198 + +0 + +0 +
    +Adelie + +176 + +0 + +0 +
    +Adelie + +202 + +0 + +0 +
    +Adelie + +186 + +0 + +0 +
    +Adelie + +199 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +210 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +197 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +199 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +191 + +0 + +0 +
    +Adelie + +200 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +188 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +192 + +0 + +0 +
    +Adelie + +185 + +0 + +0 +
    +Adelie + +190 + +0 + +0 +
    +Adelie + +184 + +0 + +0 +
    +Adelie + +195 + +0 + +0 +
    +Adelie + +193 + +0 + +0 +
    +Adelie + +187 + +0 + +0 +
    +Adelie + +201 + +0 + +0 +
    +Gentoo + +211 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +218 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +211 + +0 + +1 +
    +Gentoo + +219 + +0 + +1 +
    +Gentoo + +209 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +214 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +214 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +217 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +221 + +0 + +1 +
    +Gentoo + +209 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +218 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +209 + +0 + +1 +
    +Gentoo + +207 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Gentoo + +219 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +225 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +217 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +225 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +225 + +0 + +1 +
    +Gentoo + +217 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +224 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +221 + +0 + +1 +
    +Gentoo + +214 + +0 + +1 +
    +Gentoo + +231 + +0 + +1 +
    +Gentoo + +219 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +229 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +223 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +221 + +0 + +1 +
    +Gentoo + +221 + +0 + +1 +
    +Gentoo + +217 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +209 + +0 + +1 +
    +Gentoo + +220 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +223 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +221 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +224 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +228 + +0 + +1 +
    +Gentoo + +218 + +0 + +1 +
    +Gentoo + +218 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +218 + +0 + +1 +
    +Gentoo + +228 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +224 + +0 + +1 +
    +Gentoo + +214 + +0 + +1 +
    +Gentoo + +226 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +203 + +0 + +1 +
    +Gentoo + +225 + +0 + +1 +
    +Gentoo + +219 + +0 + +1 +
    +Gentoo + +228 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +228 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +210 + +0 + +1 +
    +Gentoo + +219 + +0 + +1 +
    +Gentoo + +208 + +0 + +1 +
    +Gentoo + +209 + +0 + +1 +
    +Gentoo + +216 + +0 + +1 +
    +Gentoo + +229 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +217 + +0 + +1 +
    +Gentoo + +230 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +214 + +0 + +1 +
    +Gentoo + +215 + +0 + +1 +
    +Gentoo + +222 + +0 + +1 +
    +Gentoo + +212 + +0 + +1 +
    +Gentoo + +213 + +0 + +1 +
    +Chinstrap + +192 + +1 + +0 +
    +Chinstrap + +196 + +1 + +0 +
    +Chinstrap + +193 + +1 + +0 +
    +Chinstrap + +188 + +1 + +0 +
    +Chinstrap + +197 + +1 + +0 +
    +Chinstrap + +198 + +1 + +0 +
    +Chinstrap + +178 + +1 + +0 +
    +Chinstrap + +197 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +198 + +1 + +0 +
    +Chinstrap + +193 + +1 + +0 +
    +Chinstrap + +194 + +1 + +0 +
    +Chinstrap + +185 + +1 + +0 +
    +Chinstrap + +201 + +1 + +0 +
    +Chinstrap + +190 + +1 + +0 +
    +Chinstrap + +201 + +1 + +0 +
    +Chinstrap + +197 + +1 + +0 +
    +Chinstrap + +181 + +1 + +0 +
    +Chinstrap + +190 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +181 + +1 + +0 +
    +Chinstrap + +191 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +193 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +197 + +1 + +0 +
    +Chinstrap + +200 + +1 + +0 +
    +Chinstrap + +200 + +1 + +0 +
    +Chinstrap + +191 + +1 + +0 +
    +Chinstrap + +205 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +201 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +203 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +199 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +210 + +1 + +0 +
    +Chinstrap + +192 + +1 + +0 +
    +Chinstrap + +205 + +1 + +0 +
    +Chinstrap + +210 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +196 + +1 + +0 +
    +Chinstrap + +196 + +1 + +0 +
    +Chinstrap + +196 + +1 + +0 +
    +Chinstrap + +201 + +1 + +0 +
    +Chinstrap + +190 + +1 + +0 +
    +Chinstrap + +212 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +198 + +1 + +0 +
    +Chinstrap + +199 + +1 + +0 +
    +Chinstrap + +201 + +1 + +0 +
    +Chinstrap + +193 + +1 + +0 +
    +Chinstrap + +203 + +1 + +0 +
    +Chinstrap + +187 + +1 + +0 +
    +Chinstrap + +197 + +1 + +0 +
    +Chinstrap + +191 + +1 + +0 +
    +Chinstrap + +203 + +1 + +0 +
    +Chinstrap + +202 + +1 + +0 +
    +Chinstrap + +194 + +1 + +0 +
    +Chinstrap + +206 + +1 + +0 +
    +Chinstrap + +189 + +1 + +0 +
    +Chinstrap + +195 + +1 + +0 +
    +Chinstrap + +207 + +1 + +0 +
    +Chinstrap + +202 + +1 + +0 +
    +Chinstrap + +193 + +1 + +0 +
    +Chinstrap + +210 + +1 + +0 +
    +Chinstrap + +198 + +1 + +0 +
    +
    +
    +

    And we get the exact same output from lm() when we throw in the new columns speciesChinstrap and speciesGentoo as the predictors!

    +
    +
    +
    broom::tidy(lm(flipper_length_mm ~ speciesChinstrap + speciesGentoo, data = penguins_explicit))
    +
    +
    +
      # A tibble: 3 x 5
    +    term             estimate std.error statistic   p.value
    +    <chr>               <dbl>     <dbl>     <dbl>     <dbl>
    +  1 (Intercept)        190.       0.552    344.   0.       
    +  2 speciesChinstrap     5.72     0.980      5.84 1.25e-  8
    +  3 speciesGentoo       27.1      0.824     32.9  2.68e-106
    +
    +

    By the way, if you’re wondering how this is practical, some modeling packages in R (like {lavaan} for structural equation modeling) only accept dummy coded variables that exist as independent columns/vectors, not as a metadata of a factor vector.16 This is common enough that some packages like {psych} have a function that does the same transformation we just did, called dummy.code()17:

    +
    +
    +
    bind_cols(
    +  penguins_implicit,
    +  psych::dummy.code(penguins_implicit$species)
    +)
    +
    +
    +
      # A tibble: 333 x 3
    +     species flipper_length_mm ...3[,"Adelie"] [,"Gentoo"] [,"Chinstrap"]
    +     <fct>               <int>           <dbl>       <dbl>          <dbl>
    +   1 Adelie                181               1           0              0
    +   2 Adelie                186               1           0              0
    +   3 Adelie                195               1           0              0
    +   4 Adelie                193               1           0              0
    +   5 Adelie                190               1           0              0
    +   6 Adelie                181               1           0              0
    +   7 Adelie                195               1           0              0
    +   8 Adelie                182               1           0              0
    +   9 Adelie                191               1           0              0
    +  10 Adelie                198               1           0              0
    +  # ... with 323 more rows
    +
    +

    feat. {data.table}

    +

    Of course, you could do all of this without reduce() in {data.table} because its walrus := is vectorized.

    +

    Here’s the {data.table} solution for our sad code:

    +
    +
    +
    library(data.table)
    +new_cols <- c("a", "b", "c")
    +
    +mtcars_dt <- mtcars %>% 
    +  head() %>% 
    +  select(mpg) %>% 
    +  as.data.table()
    +
    +mtcars_dt[, (new_cols) := NA][]
    +
    +
    +
          mpg  a  b  c
    +  1: 21.0 NA NA NA
    +  2: 21.0 NA NA NA
    +  3: 22.8 NA NA NA
    +  4: 21.4 NA NA NA
    +  5: 18.7 NA NA NA
    +  6: 18.1 NA NA NA
    +
    +

    And here’s a {data.table} solution for the explicit dummy coding example:

    +
    +
    +
    penguins_dt <- as.data.table(penguins_implicit)
    +
    +treatment_lvls <- levels(penguins_dt$species)[-1]
    +treatment_cols <- paste0("species", treatment_lvls)
    +
    +penguins_dt[, (treatment_cols) := lapply(treatment_lvls, function(x){as.integer(species == x)})][]
    +
    +
    +
             species flipper_length_mm speciesChinstrap speciesGentoo
    +    1:    Adelie               181                0             0
    +    2:    Adelie               186                0             0
    +    3:    Adelie               195                0             0
    +    4:    Adelie               193                0             0
    +    5:    Adelie               190                0             0
    +   ---                                                           
    +  329: Chinstrap               207                1             0
    +  330: Chinstrap               202                1             0
    +  331: Chinstrap               193                1             0
    +  332: Chinstrap               210                1             0
    +  333: Chinstrap               198                1             0
    +
    +

    I personally default to using {data.table} over {dplyr} in these cases.

    +

    Misc.

    +

    You can also pass in a list of functions instead of a list of arguments because why not.

    +

    For example, this replicates the very first code I showed in this blog post:

    +
    +
    +
    my_funs <- list(deviation, square, mean, sqrt)
    +
    +reduce(
    +  my_funs,
    +  ~ .y(.x),
    +  .init = nums
    +)
    +
    +
    +
      [1] 0.3039881
    +
    +

    You could also pass in both a list of functions and a list of their arguments if you really want to abstract away from, like, literally everything:

    +
    +
    +

    Lawful Good

    +
    +
    +
    library(janitor)
    +
    +mtcars %>% 
    +  clean_names(case = "title") %>% 
    +  tabyl(2) %>% 
    +  adorn_rounding(digits = 2) %>% 
    +  adorn_totals()
    +
    +
    +
         Cyl  n percent
    +       4 11    0.34
    +       6  7    0.22
    +       8 14    0.44
    +   Total 32    1.00
    +
    +
    +
    +

    Chaotic Evil

    +
    +
    +
    janitor_funs <- list(clean_names, tabyl, adorn_rounding, adorn_totals)
    +janitor_args <- list(list(case = "title"), list(2), list(digits = 2), NULL)
    +
    +reduce2(
    +  janitor_funs,
    +  janitor_args,
    +  ~ do.call(..2, c(list(dat = ..1), ..3)),
    +  .init = mtcars
    +)
    +
    +
    +
         Cyl  n percent
    +       4 11    0.34
    +       6  7    0.22
    +       8 14    0.44
    +   Total 32    1.00
    +
    +
    +
    +

    Have fun reducing repetitions in your code with reduce()!

    +
    +
    +
    +
      +
    1. So much so that there’s going to be a native pipe operator!↩︎

    2. +
    3. Taken from Advanced R Ch. 6↩︎

    4. +
    5. If you aren’t familiar with {kableExtra}, you just need to know that column_spec() can take a column index as its first argument and a color as the background argument to set the background color of a column to the provided color. And as we see here, if a color vector is passed into background, it’s just recycled to color the rows which is not what we want.↩︎

    6. +
    7. If this is your first time seeing the “bang bang” !! operator and the “walrus” := operator being used this way, check out the documentation on quasiquotation.↩︎

    8. +
    9. For those of you more familiar with quasiquation in {dplyr}, I should also mention that using “big bang” !!! like in mutate(!!!new_cols := NA) doesn’t work either. As far as I know, := is just an alias of = for the {rlang} parser, and as we know = cannot assign more than one variable at once (unlike Python, for example), which explains the error.↩︎

    10. +
    11. Note that there are more motivated usescases of reduce() out there, mostly in doing mathy-things, and I’m by no means advocating that you should always use reduce() in our context - I just think it’s fun to play around with!↩︎

    12. +
    13. There’s also .dir argument that allows you to specify the direction, but not relevant here because when you pipe, the left-hand side is always the first input to the next function.↩︎

    14. +
    15. If it helps, think of it like ((((1 + 2) + 3) + 4) + 5)↩︎

    16. +
    17. The function passed into reduce() doesn’t have to be in {rlang} anonymous function syntax, but I like it so I’ll keep using it here.↩︎

    18. +
    19. By the way, we could also do this with purrr::map() since multiple ggplot2 layers can be stored into a list and added all together in one step. But then we can’t do this cool thing I’m going to show with accumulate() next!↩︎

    20. +
    21. By the way, if you want a whole package dedicated to animating and incrementally building {ggplot2} code, check out @EvaMaeRey’s {flipbookr} package!↩︎

    22. +
    23. We are still “iterating” over the numbers and background_colors vectors but in a round-about way by passing a vector of indices for reduce() to iterate over instead and using the indices to access elements of the two vectors. This actually seems like the way to go when you have more than two varying arguments because there’s no pmap() equavalent for reduce() like preduce().↩︎

    24. +
    25. Note that we couldn’t do this with + in our {ggplot2} example because geom_point() doesn’t take a ggplot object as its first argument. Basically, the + operator is re-purposed as a class method for ggplot objects but it’s kinda complicated so that’s all I’ll say about that.↩︎

    26. +
    27. Note the use of as.character() to make sure that the left-hand side of the walrus := is converted from numeric to character. Alternatively, using the new glue syntax support from dplyr > 1.0.0, we can simplify !!as.character(.y) := to "{.y}" :=↩︎

    28. +
    29. If you aren’t familiar with linear models in R, we know that “Adelie” is the reference level because there is no “speciesAdelie” term. The estimate for “Adelie” is represented by the “(Intercept)”!↩︎

    30. +
    31. Figuring this out has caused some headaches and that’s what I get for not carefully reading the docs↩︎

    32. +
    33. Except dummy.code() also returns a column for the reference level whose value is always 1, which is kinda pointless↩︎

    34. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/reduce_ggplot.png b/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/reduce_ggplot.png new file mode 100644 index 00000000..ab6fecea Binary files /dev/null and b/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/reduce_ggplot.png differ diff --git a/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/table_anim.gif b/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/table_anim.gif new file mode 100644 index 00000000..2655682a Binary files /dev/null and b/docs/posts/2020-12-13-collapse-repetitive-piping-with-reduce/table_anim.gif differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table.png new file mode 100644 index 00000000..a5574d09 Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table.png differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table_annotated.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table_annotated.png new file mode 100644 index 00000000..d54768fb Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/samples_data_table_annotated.png differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/img/table_imgs_animated.gif b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/table_imgs_animated.gif new file mode 100644 index 00000000..39cfb158 Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/table_imgs_animated.gif differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl1.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl1.png new file mode 100644 index 00000000..051c14c5 Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl1.png differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl10.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl10.png new file mode 100644 index 00000000..6455e2fb Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/img/tbl10.png differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/index.html b/docs/posts/2021-01-17-random-sampling-a-table-animation/index.html new file mode 100644 index 00000000..3566f9c9 --- /dev/null +++ b/docs/posts/2021-01-17-random-sampling-a-table-animation/index.html @@ -0,0 +1,6025 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Random Sampling: A table animation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Random Sampling: A table animation

    + + + +

    Plus a convenient way of rendering LaTeX expressions as images

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    01-17-2021 +
    + +
    +
    + +
    +
    + +
    +

    In my last blogpost, I demonstrated a couple use cases for the higher-order functionals reduce() and accumulate() from the {purrr} package. In one example, I made an animated {kableExtra} table by accumulate()-ing over multiple calls to column_spec() that set a background color for a column.

    +

    Animated tables are virtually non-existent in the wild, and probably for a good reason. but I wanted to extend upon my previous table animation and create something that’s maybe a bit more on the “informative” side.

    +

    To that end, here’s an animate table that simulates sampling from a bivariate normal distribution.

    +

    Static

    +

    Let’s first start by generating 100,000 data points:

    +
    +
    +
    set.seed(2021)
    +
    +library(dplyr)
    +
    +samples_data <- MASS::mvrnorm(1e5, c(0, 0), matrix(c(1, .7, .7, 1), ncol = 2)) %>% 
    +  as_tibble(.name_repair = ~c("x", "y")) %>% 
    +  mutate(across(everything(), ~ as.character(.x - .x %% 0.2)))
    +
    +samples_data
    +
    +
    +
      # A tibble: 100,000 x 2
    +     x     y    
    +     <chr> <chr>
    +   1 0     -0.4 
    +   2 0.2   0.6  
    +   3 0.4   0.2  
    +   4 0.6   -0.2 
    +   5 0.6   0.8  
    +   6 -1.8  -2   
    +   7 0.8   -0.6 
    +   8 1.2   0.4  
    +   9 0.4   -0.4 
    +  10 1.4   1.6  
    +  # ... with 99,990 more rows
    +
    +

    Let’s see how this looks when we turn this into a “matrix”1. To place continuous values into discrete cells in the table, I’m also binning both variables by 0.2:

    +
    +
    +
    samples_data_spread <- samples_data %>% 
    +  count(x, y) %>% 
    +  right_join(
    +    tidyr::crossing(
    +      x = as.character(seq(-3, 3, 0.2)),
    +      y = as.character(seq(-3, 3, 0.2))
    +    ),
    +    by = c("x", "y")
    +  ) %>% 
    +  tidyr::pivot_wider(names_from = y, values_from = n) %>% 
    +  arrange(-as.numeric(x)) %>% 
    +  select(c("x", as.character(seq(-3, 3, 0.2)))) %>% 
    +  rename(" " = x)
    +
    +samples_data_spread
    +
    +
    +
      # A tibble: 31 x 32
    +     ` `    `-3` `-2.8` `-2.6` `-2.4` `-2.2`  `-2` `-1.8` `-1.6` `-1.4` `-1.2`
    +     <chr> <int>  <int>  <int>  <int>  <int> <int>  <int>  <int>  <int>  <int>
    +   1 3        NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   2 2.8      NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   3 2.6      NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   4 2.4      NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   5 2.2      NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   6 2        NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   7 1.8      NA     NA     NA     NA     NA    NA     NA     NA     NA     NA
    +   8 1.6      NA     NA     NA     NA     NA    NA     NA      1      1      4
    +   9 1.4      NA     NA     NA     NA     NA    NA      1     NA      1      4
    +  10 1.2      NA     NA     NA     NA     NA    NA     NA      3      2      7
    +  # ... with 21 more rows, and 21 more variables: `-1` <int>, `-0.8` <int>,
    +  #   `-0.6` <int>, `-0.4` <int>, `-0.2` <int>, `0` <int>, `0.2` <int>,
    +  #   `0.4` <int>, `0.6` <int>, `0.8` <int>, `1` <int>, `1.2` <int>, `1.4` <int>,
    +  #   `1.6` <int>, `1.8` <int>, `2` <int>, `2.2` <int>, `2.4` <int>, `2.6` <int>,
    +  #   `2.8` <int>, `3` <int>
    +
    +

    Now we can turn this into a table and fill the cells according to the counts using reduce():

    +
    +
    +
    library(kableExtra)
    +
    +samples_data_table <- samples_data_spread %>% 
    +  kable() %>% 
    +  kable_classic() %>% 
    +  purrr::reduce(2L:length(samples_data_spread), ~ {
    +    column_spec(
    +      kable_input = .x,
    +      column = .y,
    +      background = spec_color(
    +        samples_data_spread[[.y]],
    +        scale_from = c(1, max(as.numeric(as.matrix(samples_data_spread)), na.rm = TRUE)),
    +        na_color = "white",
    +        option = "plasma"
    +      ),
    +      color = "white"
    +    )},
    +    .init = .
    +  )
    +
    +samples_data_table
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +-3 + +-2.8 + +-2.6 + +-2.4 + +-2.2 + +-2 + +-1.8 + +-1.6 + +-1.4 + +-1.2 + +-1 + +-0.8 + +-0.6 + +-0.4 + +-0.2 + +0 + +0.2 + +0.4 + +0.6 + +0.8 + +1 + +1.2 + +1.4 + +1.6 + +1.8 + +2 + +2.2 + +2.4 + +2.6 + +2.8 + +3 +
    +3 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +2 + +1 + +1 + +8 + +2 + +7 + +7 + +8 + +4 + +6 + +6 + +2 + +1 +
    +2.8 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +2 + +NA + +3 + +6 + +6 + +20 + +14 + +20 + +15 + +8 + +18 + +6 + +10 + +7 + +3 +
    +2.6 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +1 + +NA + +7 + +11 + +21 + +26 + +17 + +26 + +29 + +28 + +21 + +17 + +10 + +3 + +8 +
    +2.4 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +1 + +7 + +11 + +17 + +20 + +32 + +33 + +43 + +52 + +43 + +37 + +23 + +23 + +17 + +9 + +7 +
    +2.2 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +1 + +3 + +7 + +6 + +12 + +20 + +18 + +46 + +51 + +59 + +66 + +58 + +73 + +53 + +41 + +21 + +20 + +16 + +8 +
    +2 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +3 + +2 + +12 + +17 + +20 + +35 + +53 + +83 + +103 + +93 + +117 + +106 + +111 + +74 + +52 + +42 + +27 + +17 + +5 +
    +1.8 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +8 + +10 + +14 + +40 + +50 + +81 + +108 + +128 + +132 + +149 + +143 + +146 + +103 + +89 + +57 + +39 + +19 + +23 + +7 +
    +1.6 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +1 + +4 + +6 + +6 + +14 + +19 + +39 + +67 + +99 + +136 + +148 + +183 + +197 + +214 + +185 + +170 + +109 + +81 + +60 + +40 + +24 + +11 + +11 +
    +1.4 + +NA + +NA + +NA + +NA + +NA + +NA + +1 + +NA + +1 + +4 + +8 + +17 + +37 + +50 + +74 + +115 + +170 + +225 + +277 + +307 + +323 + +292 + +243 + +186 + +123 + +110 + +61 + +47 + +19 + +7 + +3 +
    +1.2 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +3 + +2 + +7 + +22 + +29 + +60 + +88 + +144 + +204 + +273 + +317 + +376 + +381 + +337 + +323 + +262 + +208 + +135 + +92 + +58 + +41 + +17 + +8 + +7 +
    +1 + +NA + +NA + +NA + +NA + +1 + +NA + +1 + +5 + +6 + +18 + +26 + +64 + +83 + +160 + +239 + +329 + +375 + +504 + +501 + +474 + +455 + +336 + +315 + +223 + +154 + +94 + +52 + +23 + +11 + +3 + +2 +
    +0.8 + +NA + +NA + +NA + +NA + +NA + +NA + +4 + +8 + +10 + +29 + +68 + +104 + +163 + +269 + +336 + +375 + +517 + +566 + +612 + +572 + +480 + +355 + +256 + +190 + +129 + +58 + +37 + +14 + +14 + +1 + +2 +
    +0.6 + +NA + +NA + +NA + +NA + +1 + +4 + +9 + +20 + +39 + +62 + +104 + +161 + +272 + +373 + +459 + +591 + +674 + +684 + +641 + +587 + +487 + +365 + +251 + +167 + +97 + +56 + +25 + +9 + +5 + +3 + +1 +
    +0.4 + +NA + +NA + +NA + +NA + +2 + +4 + +27 + +32 + +60 + +101 + +159 + +260 + +413 + +535 + +680 + +794 + +796 + +780 + +704 + +537 + +452 + +345 + +218 + +119 + +69 + +38 + +16 + +8 + +10 + +1 + +NA +
    +0.2 + +NA + +NA + +1 + +2 + +2 + +9 + +33 + +46 + +91 + +152 + +229 + +388 + +519 + +654 + +777 + +851 + +881 + +712 + +674 + +535 + +389 + +285 + +176 + +102 + +45 + +29 + +14 + +7 + +4 + +1 + +NA +
    +0 + +NA + +NA + +1 + +2 + +11 + +18 + +51 + +77 + +154 + +210 + +351 + +521 + +645 + +778 + +876 + +866 + +812 + +685 + +593 + +459 + +296 + +190 + +117 + +50 + +39 + +24 + +8 + +2 + +2 + +2 + +NA +
    +-0.2 + +NA + +2 + +1 + +6 + +15 + +36 + +59 + +112 + +196 + +286 + +410 + +620 + +747 + +856 + +854 + +836 + +721 + +683 + +493 + +344 + +215 + +162 + +70 + +50 + +21 + +6 + +5 + +1 + +2 + +NA + +NA +
    +-0.4 + +NA + +1 + +2 + +12 + +24 + +60 + +85 + +168 + +256 + +373 + +551 + +689 + +785 + +842 + +776 + +773 + +683 + +504 + +395 + +233 + +154 + +94 + +43 + +35 + +7 + +4 + +4 + +NA + +1 + +NA + +NA +
    +-0.6 + +NA + +4 + +13 + +16 + +30 + +62 + +119 + +219 + +331 + +447 + +573 + +714 + +736 + +787 + +725 + +658 + +524 + +389 + +255 + +219 + +108 + +66 + +37 + +5 + +8 + +2 + +NA + +NA + +NA + +NA + +NA +
    +-0.8 + +3 + +8 + +13 + +40 + +59 + +81 + +181 + +263 + +330 + +469 + +600 + +661 + +681 + +652 + +639 + +484 + +368 + +274 + +160 + +123 + +48 + +26 + +13 + +10 + +3 + +1 + +NA + +NA + +NA + +NA + +NA +
    +-1 + +6 + +8 + +21 + +34 + +80 + +133 + +195 + +293 + +386 + +457 + +556 + +626 + +574 + +526 + +461 + +363 + +246 + +190 + +105 + +56 + +26 + +16 + +6 + +1 + +1 + +NA + +NA + +NA + +NA + +NA + +NA +
    +-1.2 + +10 + +8 + +21 + +45 + +77 + +146 + +198 + +266 + +360 + +436 + +469 + +480 + +457 + +393 + +344 + +242 + +169 + +104 + +79 + +33 + +23 + +9 + +2 + +3 + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-1.4 + +6 + +13 + +31 + +62 + +96 + +163 + +200 + +299 + +337 + +360 + +364 + +364 + +319 + +239 + +190 + +129 + +84 + +50 + +33 + +17 + +11 + +7 + +NA + +1 + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-1.6 + +18 + +25 + +39 + +61 + +110 + +138 + +184 + +235 + +281 + +278 + +294 + +246 + +211 + +176 + +148 + +92 + +40 + +23 + +17 + +8 + +5 + +3 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-1.8 + +11 + +19 + +33 + +52 + +90 + +139 + +165 + +185 + +225 + +192 + +206 + +157 + +125 + +100 + +62 + +40 + +28 + +11 + +10 + +2 + +1 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-2 + +11 + +29 + +34 + +50 + +78 + +102 + +139 + +141 + +144 + +149 + +110 + +104 + +76 + +49 + +41 + +19 + +19 + +5 + +4 + +2 + +NA + +1 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-2.2 + +11 + +23 + +38 + +48 + +76 + +76 + +99 + +105 + +88 + +81 + +81 + +72 + +36 + +20 + +25 + +9 + +6 + +4 + +2 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-2.4 + +12 + +21 + +24 + +44 + +56 + +53 + +51 + +69 + +66 + +54 + +46 + +24 + +21 + +9 + +5 + +7 + +3 + +1 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-2.6 + +12 + +15 + +20 + +34 + +32 + +30 + +40 + +34 + +36 + +28 + +21 + +15 + +8 + +4 + +2 + +1 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-2.8 + +5 + +17 + +28 + +27 + +19 + +14 + +20 + +26 + +15 + +10 + +10 + +4 + +2 + +4 + +1 + +2 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +-3 + +6 + +10 + +3 + +11 + +21 + +11 + +13 + +6 + +10 + +8 + +4 + +1 + +1 + +3 + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA + +NA +
    +
    +

    An aside on LaTeX equations

    +

    As an aside, let’s say we also want to annotate this table with the true distribution where this sample came from. As specified in our call to MASS::mvrnorm() used to make samples_data, the distribution is one where both variables have a mean of 0 and a standard deviation of 1, plus a correlation of 0.7:

    +

    \[\begin{bmatrix} X \\ Y \end{bmatrix}\ \sim\ N(\begin{bmatrix} 0 \\ 0 \end{bmatrix},\begin{bmatrix}1 & 0.7 \\ 0.7 & 1 \end{bmatrix})\]

    +

    Where the LaTeX code for the above formula is:

    +
    +
      \begin{bmatrix} X \\ Y \end{bmatrix}\ \sim\
    +  N(\begin{bmatrix} 0 \\ 0 \end{bmatrix},
    +  \begin{bmatrix}1 & 0.7 \\ 0.7 & 1 \end{bmatrix})
    +
    +

    Many different solutions already exist to LaTeX math annotations. The most common is probably Non-Standard Evaluation (NSE) methods using parse(), expression(), bquote() etc. There are bulkier solutions like the {latex2exp} package that plots plotmath expressions, though it hasn’t been updated since 2015 and I personally had difficulty getting it to work.

    +

    One solution I’ve never heard of/considered before is querying a web LaTeX editor that has an API. The Online LaTeX Equation Editor by CodeCogs is the perfect example of this. A simple link that contains the LaTeX code in a URL-compatible encoding renders the resulting expression as an image!

    +

    I wrote a function latex_query (not thoroughly tested) in my personal package that takes LaTeX code and generates a CodeCogs URL containing the rendered expression2

    +
    +
    +
    # NOTE the string literal syntax using r"(...)" is only available in R 4.0.0 and up
    +latex_url <- junebug::latex_query(
    +  formula = r"(\begin{bmatrix} X \\ Y \end{bmatrix}\ \sim\
    +              N(\begin{bmatrix} 0 \\ 0 \end{bmatrix},
    +              \begin{bmatrix}1 & 0.7 \\ 0.7 & 1 \end{bmatrix}))",
    +  dpi = 150
    +)
    +
    +knitr::include_graphics(latex_url)
    +
    +
    +

    +
    +

    The variable latex_url is this really long URL which, as we see above, points to a rendered image of the LaTeX expression we fed it!

    +

    Annotating our table, then, is pretty straightforward. We save it as an image, read in the LaTeX equation as an image, then combine!

    +
    +
    +
    save_kable(samples_data_table, "img/samples_data_table.png")
    +
    +library(magick)
    +
    +image_composite(
    +  image_read("img/samples_data_table.png"),
    +  image_read(latex_url),
    +  offset = "+50+50"
    +)
    +
    +
    +
    +
    +

    +
    +

    Animated

    +

    For an animated version, we add a step where we split the data at every 10,000 additional samples before binning the observations into cells. We then draw a table at each point of the accumulation using {kableExtra} with the help of map() and reduce() (plus some more kable styling).

    +
    +
    +
    samples_tables <- purrr::map(1L:10L, ~{
    +  samples_slice <- samples_data %>% 
    +    slice(1L:(.x * 1e4)) %>% 
    +    count(x, y) %>% 
    +    right_join(
    +      tidyr::crossing(
    +        x = as.character(seq(-3, 3, 0.2)),
    +        y = as.character(seq(-3, 3, 0.2))
    +      ),
    +      by = c("x", "y")
    +    ) %>% 
    +    tidyr::pivot_wider(names_from = y, values_from = n) %>% 
    +    arrange(-as.numeric(x)) %>% 
    +    select(c("x", as.character(seq(-3, 3, 0.2)))) %>% 
    +    rename(" " = x)
    +
    +  
    +  samples_slice %>%
    +    kable() %>% 
    +    kable_classic() %>% 
    +    purrr::reduce(
    +      2L:length(samples_slice),
    +      ~ {
    +        .x %>% 
    +          column_spec(
    +            column = .y,
    +            width_min = "35px",
    +            background = spec_color(
    +              samples_slice[[.y]],
    +              scale_from = c(1, max(as.numeric(as.matrix(samples_slice)), na.rm = TRUE)),
    +              na_color = "white",
    +              option = "plasma"
    +            ),
    +            color = "white"
    +          ) %>% 
    +          row_spec(
    +            row = .y - 1L,
    +            hline_after = FALSE,
    +            extra_css = "border-top:none; padding-top:15px;"
    +          )
    +      },
    +      .init = .
    +    ) %>% 
    +    row_spec(0L, bold = TRUE) %>% 
    +    column_spec(1L, bold = TRUE, border_right = TRUE) %>% 
    +    kable_styling(
    +      full_width = F,
    +      font_size = 10,
    +      html_font = "IBM Plex Mono",
    +    )
    +})
    +
    +
    +
    +

    The result, samples_tables is a list of tables. We can walk() over that list with save_kable() to write them as images and then read them back in with {magick}:

    +
    +
    +
    purrr::iwalk(samples_tables, ~ save_kable(.x, file = glue::glue("tbl_imgs/tbl{.y}.png")))
    +
    +table_imgs <- image_read(paste0("tbl_imgs/tbl", 1:10, ".png"))
    +
    +
    +
    +

    Now we can add our LaTeX expression from the previous section as an annotation to these table images using image_composite():

    +
    +
    +
    table_imgs_annotated <- table_imgs %>% 
    +  image_composite(
    +    image_read(latex_url),
    +    offset = "+100+80"
    +  )
    +
    +
    +
    +

    Finally, we just patch the table images together into an animation using image_animate() and we have our animated table!

    +
    +
    +
    table_imgs_animated <- table_imgs_annotated %>% 
    +  image_animate(optimize = TRUE)
    +
    +
    +
    +

    Final Product

    +
    +

    +
    +

    You can also see the difference in the degree of “interpolation” by directly comparing the table at 10 thousand vs 100 thousand samples (the first and last frames):

    +
    +

    +
    +

    Neat!

    +
    +
    +
    +
      +
    1. Visually speaking. It’s still a dataframe object for compatibility with {kableExtra}↩︎

    2. +
    3. Details about the API - https://www.codecogs.com/latex/editor-api.php↩︎

    4. +
    +
    + + + +
    + +
    +
    + + + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/random-sampling-a-table-animation_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/random-sampling-a-table-animation_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..39fcb447 Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/random-sampling-a-table-animation_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2021-01-17-random-sampling-a-table-animation/table_preview.png b/docs/posts/2021-01-17-random-sampling-a-table-animation/table_preview.png new file mode 100644 index 00000000..8b6efa86 Binary files /dev/null and b/docs/posts/2021-01-17-random-sampling-a-table-animation/table_preview.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya.png new file mode 100644 index 00000000..47e0333a Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya_word.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya_word.png new file mode 100644 index 00000000..de81426b Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/alegreya_word.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/fa_otf.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/fa_otf.png new file mode 100644 index 00000000..e8d4ea0e Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/fa_otf.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/inkscape_svg.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/inkscape_svg.png new file mode 100644 index 00000000..ebbfa8d8 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/img/inkscape_svg.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/index.html b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/index.html new file mode 100644 index 00000000..f44deaa4 --- /dev/null +++ b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/index.html @@ -0,0 +1,3450 @@ + + + + + + + + + + + + + + + + + + + +June Choe: Setting up and debugging custom fonts + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Setting up and debugging custom fonts

    + + + +

    A practical introduction to all (new) things font in R

    +
    + +
    + June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/ + +
    06-24-2021 +
    + +
    + +
    +

    This blog post was featured in the R Weekly highlights podcast! Thanks to the R Weekly team for the comprehensive review!

    +

    An important point of clarification (30/07/2021): Many people are familiar with {showtext} and {extrafont}, and may even have existing workflows centered around those packages. In this blog post, there is no “installing” of fonts of any sort within the R session. The magic here is that {ragg} is designed to directly access the fonts installed on your system (with some caveats as described in detail later). This issue of the graphics device is independent of the kind of things that {showtext} and {extrafont} does, which is why they’re not relevant here.

    +

    tl;dr: don’t use {showtext} and don’t use {extrafont} when following the workflow described in this blog post!1

    +
    +

    Introduction

    +

    Getting custom fonts to work in R has historically been pretty difficult.2 At a high level, it involves the non-trivial task of unifying the graphics device, the operating system, and text rendering, (and also in our case, R!) to seamlessly work with each other.

    +

    Luckily for us in 2021, we have an amazing solution to this problem thanks to recent developments in the {ragg}, {systemfonts}, and {textshaping} packages by RStudio. This is great news because a lot of the work for getting custom fonts to work in R is already done for us!

    +

    In this blog post, I’ll start with the basics of setting up custom fonts followed by a walkthrough of the font debugging workflow, concluding with some practical use-cases that can spice up your typography game for data viz. 

    +

    Setting up {ragg}

    +

    The first thing you should do, if you haven’t already, is to install {ragg}, {systemfonts}, and {textshaping}.

    +
    +
    +
    install.packages('ragg')
    +install.packages('systemfonts')
    +install.packages('textshaping')
    +
    +
    +
    +

    Next, we want to make sure that whenever we output a plot3, we do so using the AGG graphics device (that’s the “agg” part of “ragg”).

    +

    There are at least four places where this is relevant:

    +

    1. Rendering in RStudio plot pane

    +

    For RStudio >= 1.4, go to Tools > Global Options > General > Graphics and set the Backend to AGG.

    +
    +
    +Where to set AGG as the graphic device for RStudio - image from https://ragg.r-lib.org +

    +Figure 1: Where to set AGG as the graphic device for RStudio - image from https://ragg.r-lib.org +

    +
    +
    +

    2. Saving as an external file

    +

    For bitmap output, use any of the ragg::agg_*() function to render plots using the AGG device.

    +
    +
    +
    # Set output path
    +pngfile <- here::here("img", "my_plot.png")
    +# Initialize device
    +ragg::agg_png(
    +  pngfile, width = 10, height = 6, units = "in",
    +  res = 300, scaling = 3
    +)
    +# Plot
    +plot(hist(mtcars$mpg))
    +# Close device
    +invisible(dev.off())
    +
    +
    +
    +

    For ggplot2 figures: as of the new ggplot2 v3.3.4 release (released 06-16-2021), ggsave() automatically defaults to rendering the output using agg_*() devices!

    +
    + +Old disclaimer for {ggplot2} < v.3.3.4 + +This long-winded way works for any plot, but if you use {ggplot2} and ggplot2::ggsave() a lot, you might wonder whether you can just pass in ragg::agg_png() into the device argument and specify the arguments in ggsave() instead. This turns out to actually not be so straightforward, but will likely be patched in the next update (v3.3.4?). 4 +
    +

    3. Rmarkdown

    +

    Pass in a {ragg} device has res and units specified to the dev argument of knitr::chunk_opts$set() at the top of the script.5

    +
    +
    +
    ragg_png = function(..., res = 150) {
    +  ragg::agg_png(..., res = res, units = "in")
    +}
    +opts_chunk$set(dev = "ragg_png")
    +
    +
    +
    +

    4. Shiny

    +

    Simply set options(shiny.useragg = TRUE) before rendering. Also check out the {thematic} package for importing/using custom fonts in shiny plot outputs.

    +

    Installing custom fonts

    +

    Now that you have {ragg} and {systemfonts} installed, take it for a spin with a custom font! When you’re rendering plots using {ragg}, custom fonts should just work as long as you have them installed on your local machine.

    +

    If you haven’t really worked with custom fonts before, “installing a custom font” simply means finding the font file on the internet, downloading it, and drag-and-drop into a special folder on your local machine. It’s something like Network/Library/Fonts for Macs and Microsoft/Windows/Fonts for Windows. There can actually be a bit more to this process6, so make sure to google and check the process for installing fonts on your machine.

    +

    Finding the right file

    +

    Font files come in many forms. In general, fonts files that match these two criteria tend to work the best:

    +
      +
    1. Fonts in .otf (OpenType Font) or .ttf (TrueType Font) formats. These are font formats that are installable on your local machine. You want to avoid other formats like .woff or .woff2, for example, which are designed for use for the web. In theory both .otf and .ttf should work with {ragg}, though I’ve sometimes had trouble with .otf. In those cases, I simply converted the .otf font file to .ttf before installing it, using free online conversion tools that you can easily find on Google. I’m of course glossing over the details here and I’m hardly an expert, but you can read more about TrueType and OpenType formats here.

    2. +
    3. Static fonts. In static fonts, each member of the family has their own set of glyphs (i.e., there is a font file for each style). This is in contrast to variable fonts, where you have a single font file which can take the form of multiple styles (either by having many sets of glyphs or variable parameters).7 To illustrate, look at the difference between the static (top) vs. variable (bottom) files for the Alegreya family.

      +
      +
      +Static font files for Alegreya +

      +Figure 2: Static font files for Alegreya +

      +
      +
      +
      +
      +Variable font files for Alegreya +

      +Figure 3: Variable font files for Alegreya +

      +
      +
      +

      We see that static fonts are differentiated from variable fonts by having a distinct file for each style, like Alegreya-Black.ttf. On the other hand, variable fonts usually say “variable” somewhere in the file name, and are slightly larger in size than any individual static member. Note that not all fonts have both static and variable files, and not all static font files are .ttf (there can be static .otf and variable .ttf files).8

    4. +
    +

    The above two images show the contents of the .zip file that you’d get if you went to Google Fonts (an awesome repository of free and open-source professional fonts) and clicked the Download family button on the page for Alegreya. If you want to use the Alegreya font family (Open Font License9) in R, then you simply drag-and-drop all the static font files in /static into your system’s font folder (or in Settings > Fonts for Windows 10).

    +

    Checking that a font is installed and available

    +

    Once you install a custom font on your system, it should also be available elsewhere locally on your machine. For example, I can use Alegreya in Microsoft Word after I download it (this is actually my first go-to sanity check).

    +
    +
    +Alegreya in Microsoft Word +

    +Figure 4: Alegreya in Microsoft Word +

    +
    +
    +

    And by extension Alegreya should now be available for figures rendered with {ragg}. Let’s try using Alegreya in ggplot by passing it to the family argument of geom_text()

    +
    +
    +
    library(ggplot2)
    +ggplot(NULL, aes(0, 0)) +
    +  geom_text(
    +    aes(label = "The Alegreya font"),
    +    size = 18, family = "Alegreya"
    +  )
    +
    +
    +

    +
    +

    It just works!

    +

    More specifically, it works because Alegreya is visible to {systemfonts}, which handles text rendering for {ragg}. If we filter list of fonts from systemfonts::system_fonts(), we indeed find the 12 styles of Alegreya from the static .ttf files that we installed!

    +
    +
    +
    library(systemfonts)
    +library(dplyr)
    +library(stringr)
    +
    +system_fonts() %>% 
    +  filter(family == "Alegreya") %>% 
    +  transmute(
    +    family, style,
    +    file = str_extract(path, "[\\w-]+\\.ttf$")
    +  )
    +
    +
    +
      # A tibble: 12 x 3
    +     family   style            file                        
    +     <chr>    <chr>            <chr>                       
    +   1 Alegreya Black Italic     Alegreya-BlackItalic.ttf    
    +   2 Alegreya Bold             Alegreya-Bold.ttf           
    +   3 Alegreya Bold Italic      Alegreya-BoldItalic.ttf     
    +   4 Alegreya ExtraBold        Alegreya-ExtraBold.ttf      
    +   5 Alegreya ExtraBold Italic Alegreya-ExtraBoldItalic.ttf
    +   6 Alegreya Italic           Alegreya-Italic.ttf         
    +   7 Alegreya Medium           Alegreya-Medium.ttf         
    +   8 Alegreya Medium Italic    Alegreya-MediumItalic.ttf   
    +   9 Alegreya Regular          Alegreya-Regular.ttf        
    +  10 Alegreya SemiBold         Alegreya-SemiBold.ttf       
    +  11 Alegreya SemiBold Italic  Alegreya-SemiBoldItalic.ttf 
    +  12 Alegreya Black            Alegreya-Black.ttf
    +
    +

    Debugging custom fonts

    +

    So far we’ve seen that the workflow for setting up and installing fonts is pretty straightforward. But what do we do in times when things inevitable go wrong?

    +

    Consider the case of using Font Awesome, an icon font that renders special character sequences as icon glyphs (check the Icon fonts section for more!). Font Awesome has a free version (CC-BY and SIL OFL license), and let’s say we want to use it for personal use for a TidyTuesday submission.

    +

    The first thing we do is locate the font file. Font Awesome is open source, and the free version (Font Awesome 5 Free) is updated on Github. The most recent release as of this blog post is v5.15.3. If you unzip the file, you’ll find .otf font files corresponding to the three variants available in the free version: Regular, Solid, and Brands.

    +
    +
    +Font Awesome 5 files +

    +Figure 5: Font Awesome 5 files +

    +
    +
    +

    Remember how I said R tends to play nicer with .ttf than .otf fonts?10 Lets go ahead and convert the .otf files using an online converter, like https://convertio.co/otf-ttf. Now, with the three font files in .ttf format, follow the instructions for installing fonts on your OS.

    +

    Once Font Awesome is installed on our local machine, it should be visible to {systemfonts}, like this:

    +
    +
    +
    system_fonts() %>% 
    +  filter(str_detect(family, "Font Awesome 5")) %>% 
    +  transmute(
    +    family, style,
    +    file = stringr::str_extract(path, "[\\w-]+\\.ttf$")
    +  )
    +
    +
    +
      # A tibble: 3 x 3
    +    family                style   file                                 
    +    <chr>                 <chr>   <chr>                                
    +  1 Font Awesome 5 Free   Solid   Font-Awesome-5-Free-Solid-900.ttf    
    +  2 Font Awesome 5 Brands Regular Font-Awesome-5-Brands-Regular-400.ttf
    +  3 Font Awesome 5 Free   Regular Font-Awesome-5-Free-Regular-400.ttf
    +
    +

    Now let’s try plotting some icons!

    +

    We see that we can render icons from the Regular variant (“clock”) and the Brands variant (“twitter”).

    +
    +
    +
    # Left plot
    +ggplot(NULL, aes(0, 0)) +
    +  geom_text(
    +    aes(label = "clock"),
    +    size = 50, family = "Font Awesome 5 Free"
    +  )
    +
    +# Right plot
    +ggplot(NULL, aes(0, 0)) +
    +  geom_text(
    +    aes(label = "twitter"),
    +    size = 50, family = "Font Awesome 5 Brands"
    +  )
    +
    +
    +

    +
    +

    But what about rendering in the Solid variant? Font Awesome tells me that the Solid variant has a “cat” icon, so let’s try it.

    +
    +
    +
    ggplot(NULL, aes(0, 0)) +
    +  geom_text(aes(label = "cat"), size = 50, family = "Font Awesome 5 Solid")
    +
    +
    +

    +
    +

    Uh oh, that didn’t work. Well that’s because Solid is actually a style, not a family! If you go back to the output from system_fonts(), we see that Font Awesome actually consists of two font families: Font Awesome 5 Brands which has a “Regular” style, and Font Awesome 5 Free with a “Regular” style and a “Solid” style.

    +

    The structure is roughly like this:

    +
    +  Font Awesome 5 Free
    +  |---  Regular
    +  |---  Solid
    +  Font Awesome 5 Brands
    +  |---  Regular
    +
    +

    In geom_text(), the font style is set by the fontface argument. When we don’t specify fontface, such as in our working example for the clock and twitter icons, it defaults to the Regular style.11

    +

    So the solution to our problem is to put in fontface = "Solid", right…?

    +
    +
    +
    ggplot(NULL, aes(0, 0)) +
    +  geom_text(
    +    aes(label = "cat"), size = 50,
    +    family = "Font Awesome 5 Free", fontface = "solid"
    +  )
    +
    +
    +
      Error in FUN(X[[i]], ...): invalid fontface solid
    +
    +

    Well now it just errors!12 The issue here runs a bit deeper: if we track down the error,13 it takes us to a function inside grid::gpar() that validates fontface. 14 If we take a look at the code, we see that only a very few font styles are valid, and “solid” isn’t one of them.

    +
    +
    +
    function (ch) 
    +switch(ch, plain = 1L, bold = 2L, italic = , oblique = 3L, bold.italic = 4L, 
    +  symbol = 5L, cyrillic = 5L, cyrillic.oblique = 6L, EUC = 7L, 
    +  stop("invalid fontface ", ch))
    +
    +
    +
    +

    Okay, so then how can we ever access the Solid style of the Font Awesome 5 Free family? Luckily, there’s a solution: use systemfonts::register_font() to register the Solid style as the “plain” style of its own font family!

    +

    We can do this by passing in the name of the new font family in the name argument, and passing the path of the font file to the plain argument.

    +
    +
    +
    fa_solid_path <- system_fonts() %>% 
    +  filter(family == "Font Awesome 5 Free", style == "Solid") %>% 
    +  pull(path)
    +
    +systemfonts::register_font(
    +  name = "Font Awesome 5 Free Solid",
    +  plain = fa_solid_path
    +)
    +
    +
    +
    +

    To check if we were successful in registering this new font variant, we can call systemfonts::registry_fonts() which returns all registered custom fonts in the current session:

    +
    +
    +
    systemfonts::registry_fonts() %>% 
    +  transmute(
    +    family, style,
    +    file = stringr::str_extract(path, "[\\w-]+\\.ttf$")
    +  )
    +
    +
    +
      # A tibble: 4 x 3
    +    family                    style       file                             
    +    <chr>                     <chr>       <chr>                            
    +  1 Font Awesome 5 Free Solid Regular     Font-Awesome-5-Free-Solid-900.ttf
    +  2 Font Awesome 5 Free Solid Bold        Font-Awesome-5-Free-Solid-900.ttf
    +  3 Font Awesome 5 Free Solid Italic      Font-Awesome-5-Free-Solid-900.ttf
    +  4 Font Awesome 5 Free Solid Bold Italic Font-Awesome-5-Free-Solid-900.ttf
    +
    +

    We see that the Solid style is now available as the Regular (a.k.a. “plain”) style of its own font family: Font Awesome 5 Free Solid!15

    +

    Now we’re back to our cat icon example. Again, because Font Awewsome says there’s a cat icon in the Solid style, we’d expect a cat icon if we render the text “cat” in the Solid style. Let’s set the family argument to our newly registered “Font Awesome 5 Free Solid” family and see what happens:

    +
    +
    +
    ggplot(NULL, aes(0, 0)) +
    +  geom_text(aes(label = "cat"), size = 50, family = "Font Awesome 5 Free Solid")
    +
    +
    +

    +
    +

    Third time’s the charm !!!

    +

    Hoisting font styles

    +

    Hopefully the lesson is now clear: to make a custom font work in R, the font must be visible to systemfonts::system_fonts() in a style that is accessible to grid::gpar(). The nifty trick of registering an inaccessible style as the “plain” style of its own family can be extended and automated as a utility function that is called purely for this side effect. In my experimental package, I have very simple function called font_hoist() which “hoists”16 all styles of a family as the “plain”/Regular style of their own families. This way, you never have to worry about things going wrong in the fontface argument.

    +
    + +junebug::font_hoist() + +
    +
    +
    font_hoist <- function(family, silent = FALSE) {
    +  font_specs <- systemfonts::system_fonts() %>%
    +    dplyr::filter(family == .env[["family"]]) %>%
    +    dplyr::mutate(family = paste(.data[["family"]], .data[["style"]])) %>%
    +    dplyr::select(plain = .data[["path"]], name = .data[["family"]])
    +
    +  purrr::pwalk(as.list(font_specs), systemfonts::register_font)
    +
    +  if (!silent)  message(paste0("Hoisted ", nrow(font_specs), " variants:\n",
    +                               paste(font_specs$name, collapse = "\n")))
    +}
    +
    +
    +
    +
    +

    Let’s apply this to our Alegreya family. As we saw earlier, it has 12 styles, but only 4 can be accessed by grid::gpar().17 But once we hoist the styles, we can access them all!

    +
    +
    +
    # install_github("yjunechoe/junebug")
    +junebug::font_hoist("Alegreya")
    +
    +
    +
      Hoisted 12 variants:
    +  Alegreya Black Italic
    +  Alegreya Bold
    +  Alegreya Bold Italic
    +  Alegreya ExtraBold
    +  Alegreya ExtraBold Italic
    +  Alegreya Italic
    +  Alegreya Medium
    +  Alegreya Medium Italic
    +  Alegreya Regular
    +  Alegreya SemiBold
    +  Alegreya SemiBold Italic
    +  Alegreya Black
    +
    +
    +
    +
    # Grab the newly registered font families
    +alegreya_styles <- systemfonts::registry_fonts() %>% 
    +  filter(str_detect(family, "Alegreya"), style == "Regular") %>% 
    +  pull(family)
    +
    +# Render a plot for all 12 styles
    +purrr::walk(
    +  alegreya_styles,
    +  ~ print(ggplot(NULL, aes(0, 0)) +
    +      geom_text(aes(label = .x), size = 14, family = .x))
    +)
    +
    +
    +

    +
    +

    But note that the registration of custom font variants is not persistent across sessions. If you restart R and run registry_fonts() again, it will return an empty data frame, indicating that you have no font variants registered. You have to register font variants for every session, which is why it’s nice to have the register_fonts() workflow wrapped into a function like font_hoist().

    +

    Advanced font features

    +

    But wait, that’s not all!

    +

    Many modern professional fonts come with OpenType features, which mostly consist of stylistic parameters that can be turned on-and-off for a font. Note that despite being called “OpenType” features, it’s not something unique to .otf font formats. TrueType fonts (.ttf) can have OpenType features as well. For a fuller picture, you can check out the full list of registered features and this article with visual examples for commonly used features.

    +

    It looks overwhelming but only a handful are relevant for data visualization. I’ll showcase two features here: lining and ordinals.

    +

    Lining

    +

    One of the most practical font features is lining, also called "lnum" (the four-letter feature tag), where all numbers share the same height and baseline.18

    +

    Let’s use our Alegreya font as an example again. By default, Alegreya has what are called “old style” numbers, where number glyphs have ascending and descending strokes which can make a string of numbers look unbalanced. Notice how the digits share different baselines here:

    +
    +
    +
    ggplot(NULL, aes(0, 0)) +
    +  geom_text(
    +    aes(label = "123456789"),
    +    size = 35, family = "Alegreya"
    +  )
    +
    +
    +

    +
    +

    Luckily, Alegreya supports the “lining” feature. We know this because the get_font_features() function from the {textshaping} package returns a lists of OpenType features supported by Alegreya, one of which is “lnum”.

    +
    + +
      [[1]]
    +   [1] "cpsp" "kern" "mark" "mkmk" "aalt" "c2sc" "case" "ccmp" "dlig" "dnom"
    +  [11] "frac" "liga" "lnum" "locl" "numr" "onum" "ordn" "pnum" "sinf" "smcp"
    +  [21] "ss01" "ss02" "ss03" "ss04" "ss05" "subs" "sups" "tnum"
    +
    +

    To access the lining feature, we can use the systemfonts::register_variant() function, which works similarly to systemfonts::register_font(). The former is simply a wrapper around the latter, and we use it here for convenience because “Alegreya” (as in, the default Regular style) is already accessible without us having to point to the font file.

    +

    To turn the lining feature on, we need to set the features argument of register_variant() using the helper function systemfonts::font_feature(). The full code looks like this:

    +
    +
    +
    systemfonts::register_variant(
    +  name = "Alegreya-lining",
    +  family = "Alegreya",
    +  features = systemfonts::font_feature(numbers = "lining")
    +)
    +
    +
    +
    +

    And again, we can see if the font variant was successfully registered by checking registry_fonts():

    +
    +
    +
    registry_fonts() %>% 
    +  filter(family == "Alegreya-lining", style == "Regular") %>% 
    +  transmute(
    +    family, style,
    +    features = names(features[[1]])
    +  )
    +
    +
    +
      # A tibble: 1 x 3
    +    family          style   features
    +    <chr>           <chr>   <chr>   
    +  1 Alegreya-lining Regular lnum
    +
    +

    And that’s it! Let’s try rendering the numbers again with the original “Alegreya” font (top) and the new “Alegreya-lining” variant (bottom):

    +
    +
    +
    ggplot(NULL) +
    +  geom_text(
    +    aes(0, 1, label = "123456789"),
    +    size = 35, family = "Alegreya") +
    +  geom_text(
    +    aes(0, 0, label = "123456789"),
    +    size = 35, family = "Alegreya-lining"
    +  ) +
    +  scale_y_continuous(expand = expansion(add = 0.5))
    +
    +
    +

    +
    +

    A subtle but noticeable difference!

    +

    If we want a font variant to have a mix of different style and OpenType features, we have to go back to register_font() (where we register styles as their own families by pointing to the files) and set the features argument there.

    +
    +
    +
    # Get file path
    +AlegreyaBlackItalic_path <- system_fonts() %>% 
    +  filter(family == "Alegreya", style == "Black Italic") %>% 
    +  pull(path)
    +
    +# Register variant
    +register_font(
    +  name = "Alegreya Black Italic-lining",
    +  plain = AlegreyaBlackItalic_path,
    +  features = font_feature(numbers = "lining")
    +)
    +
    +ggplot(NULL) +
    +  geom_text(
    +    aes(0, 1, label = "123456789"),
    +    size = 35, family = "Alegreya Black Italic"
    +  ) +
    +  geom_text(
    +    aes(0, 0, label = "123456789"),
    +    size = 35, family = "Alegreya Black Italic-lining"
    +  ) +
    +  scale_y_continuous(expand = expansion(add = 0.5))
    +
    +
    +

    +
    +

    Ordinals

    +

    Ordinals (or “ordn”) is a font feature which works almost like a superscript. It targets all lower case letters, and is intended for formatting ordinals like 1st, 2nd, 3rd.

    +

    Let’s try it out!

    +

    First, we check that “ordn” is supported for Alegreya:

    +
    +
    +
    "ordn" %in% unlist(get_font_features("Alegreya"))
    +
    +
    +
      [1] TRUE
    +
    +

    Then, we register the ordinal variant. Note that “ordn” is not built-in as an option for the letters argument of font_features(), unlike “lnum” which is a built-in option for the numbers argument.19 Therefore, we have to set the “ordn” feature inside the ... of font_feature() with "ordn" = TRUE. And let’s also simultaneously turn on the lining feature from before as well.

    +
    +
    +
    # Register variant
    +register_variant(
    +  name = "Alegreya-lnum_ordn",
    +  family = "Alegreya",
    +  features = font_feature(numbers = "lining", "ordn" = TRUE)
    +)
    +
    +# Double check registration
    +registry_fonts() %>% 
    +  filter(family == "Alegreya-lnum_ordn", style == "Regular") %>% 
    +  pull(features)
    +
    +
    +
      [[1]]
    +  ordn lnum 
    +     1    1
    +
    +
    +
    +
    ggplot(NULL) +
    +  geom_text(
    +    aes(0, 1, label = "1st 2nd 3rd 4th"),
    +    size = 20, family = "Alegreya"
    +  ) +
    +  geom_text(
    +    aes(0, 0, label = "1st 2nd 3rd 4th"),
    +    size = 20, family = "Alegreya-lnum_ordn"
    +  ) +
    +  scale_y_continuous(expand = expansion(add = 0.5))
    +
    +
    +

    +
    +

    Again, it’s important to note that this targets all lower case letters. So something like this renders awkwardly:

    +
    +
    +
    ggplot(NULL) +
    +  geom_text(
    +    aes(0, 0, label = "June 16th 2021"),
    +    size = 20, family = "Alegreya-lnum_ordn"
    +  )
    +
    +
    +

    +
    +

    We could turn “June” into all caps, but that still looks pretty ugly:

    +
    +
    +
    ggplot(NULL) +
    +  geom_text(
    +    aes(0, 0, label = "JUNE 16th 2021"),
    +    size = 20, family = "Alegreya-lnum_ordn"
    +  )
    +
    +
    +

    +
    +

    One solution is to render the month in the Regular style and the rest in the ordinal variant.20 We can combine text in multiple fonts in-line with html syntax supported by geom_richtext() from {ggtext}. If you’re already familiar with {ggtext}, this example shows that it works the same for registered custom font variants!

    +
    +
    +
    library(ggtext)
    +
    +formatted_date <- "<span style='font-family:Alegreya-lnum_ordn'>16th 2021</span>"
    +
    +ggplot(NULL) +
    +  geom_richtext(
    +    aes(0, 0, label = paste("June", formatted_date)),
    +    size = 20, family = "Alegreya",
    +    fill = NA, label.color = NA
    +  )
    +
    +
    +

    +
    +

    What’s extra nice about this is that while {ggtext} already supports the <sup> html tag (which formats text as superscript), it’s not as good as the ordinals font feature. Look how the generic <sup> solution (top) doesn’t look as aesthetically pleasing in comparison:

    +
    +
    +
    sups <- "1<sup>st</sup> 2<sup>nd</sup> 3<sup>rd</sup> 4<sup>th</sup>"
    +
    +ggplot(NULL) +
    +  geom_richtext(
    +    aes(0, 1, label = sups),
    +    size = 25, family = "Alegreya-lining",
    +    fill = NA, label.color = NA
    +  ) +
    +  geom_text(
    +    aes(0, 0, label = "1st 2nd 3rd 4th"),
    +    size = 25, family = "Alegreya-lnum_ordn"
    +  ) +
    +  scale_y_continuous(expand = expansion(add = 0.5))
    +
    +
    +

    +
    +

    In my opinion, you should always err towards using the supported font features because they are designed with the particular aesthetics of the font in mind.21 Hopefully this example has convinced you!

    +

    Usecases

    +

    A mash-up

    +

    Here’s a made up plot that mashes up everything we went over so far:

    +
    +

    +
    +
    + +Plot Code + +
    +
    +
    # Setting up fonts (repeat from above)
    +junebug::font_hoist("Font Awesome 5 Free")
    +junebug::font_hoist("Alegreya")
    +
    +systemfonts::register_variant(
    +  name = "Alegreya-lining",
    +  family = "Alegreya",
    +  features = systemfonts::font_feature(numbers = "lining")
    +)
    +systemfonts::register_variant(
    +  name = "Alegreya-lnum_ordn",
    +  family = "Alegreya",
    +  features = systemfonts::font_feature(numbers = "lining", "ordn" = TRUE)
    +)
    +
    +# labelling function for ordinal format
    +ordinal_style <- function(ordn) {
    +  function (x) {
    +    scales::ordinal_format()(as.integer(x)) %>% 
    +      stringr::str_replace(
    +        "([a-z]+)$",
    +        stringr::str_glue("<span style='font-family:{ordn}'>\\1</span>")
    +      )
    +  }
    +}
    +
    +# data
    +set.seed(2021)
    +ordinal_data <- tibble(
    +  Quarter = as.factor(1:4),
    +  Earnings = c(9, 7, 6, 3) * 1e6
    +) %>% 
    +  arrange(desc(Earnings)) %>% 
    +  mutate(
    +    Mood = c("smile-beam", "meh-blank", "meh", "dizzy"),
    +    color = c("forestgreen", "goldenrod", "goldenrod", "firebrick")
    +  )
    +
    +# plot
    +ggplot(ordinal_data, aes(Quarter, Earnings)) +
    +  geom_text(
    +    aes(label = Mood, color = color),
    +    size = 18, family = "Font Awesome 5 Free Solid"
    +  ) +
    +  scale_color_identity() +
    +  scale_y_continuous(
    +    name = NULL,
    +    labels = scales::label_dollar(),
    +    expand = expansion(0.3)
    +  ) +
    +  scale_x_discrete(
    +    labels = ordinal_style("Alegreya-lnum_ordn")
    +  ) +
    +  labs(title = "Quarterly Earnings") +
    +  theme_classic() +
    +  theme(
    +    text = element_text(
    +      size = 14,
    +      family = "Alegreya"
    +    ),
    +    axis.text.x = ggtext::element_markdown(
    +      size = 18,
    +      color = "black",
    +      family = "Alegreya-lining"
    +    ),
    +    axis.text.y = element_text(
    +      size= 14,
    +      color = "black",
    +      family = "Alegreya-lining"
    +    ),
    +    axis.ticks.x = element_blank(),
    +    axis.title.x = element_text(
    +      size = 18,
    +      family = "Alegreya Medium"
    +    ),
    +    plot.title = element_text(
    +      size = 24,
    +      family = "Alegreya Black",
    +      margin = margin(b = 5, unit = "mm")
    +    )
    +  )
    +
    +
    +
    +
    +

    Icon fonts

    +

    If this blog post was your first time encountering icon fonts in R, you probably have a lot of questions right now about using them in data visualizations. You can check out my lightning talk on icon fonts that I gave at RLadies Philly for a quick overview as well as some tips & tricks!

    +

    +

    +
    + +
    +

    Some extra stuff not mentioned in the talk:

    + +

    More by others

    + +

    Official RStudio blog posts:

    + +

    Session info

    +
    + +Session Info + +
    +
      R version 4.1.0 (2021-05-18)
    +  Platform: x86_64-w64-mingw32/x64 (64-bit)
    +  Running under: Windows 10 x64 (build 19042)
    +  
    +  Matrix products: default
    +  
    +  locale:
    +  [1] LC_COLLATE=English_United States.1252 
    +  [2] LC_CTYPE=English_United States.1252   
    +  [3] LC_MONETARY=English_United States.1252
    +  [4] LC_NUMERIC=C                          
    +  [5] LC_TIME=English_United States.1252    
    +  
    +  attached base packages:
    +  [1] stats     graphics  grDevices utils     datasets  methods   base     
    +  
    +  other attached packages:
    +  [1] ggtext_0.1.1      textshaping_0.3.4 stringr_1.4.0     dplyr_1.0.7      
    +  [5] systemfonts_1.0.2 ggplot2_3.3.5     knitr_1.33       
    +  
    +  loaded via a namespace (and not attached):
    +   [1] tidyselect_1.1.1   xfun_0.22          bslib_0.2.5.1      purrr_0.3.4       
    +   [5] colorspace_2.0-2   vctrs_0.3.8        generics_0.1.0     htmltools_0.5.1.1 
    +   [9] yaml_2.2.1         utf8_1.1.4         rlang_0.4.11       gridtext_0.1.4    
    +  [13] jquerylib_0.1.3    pillar_1.6.1       glue_1.4.2         withr_2.4.2       
    +  [17] DBI_1.1.1          fortunes_1.5-4     lifecycle_1.0.0    munsell_0.5.0     
    +  [21] junebug_0.0.0.9000 gtable_0.3.0       ragg_1.1.3         evaluate_0.14     
    +  [25] labeling_0.4.2     markdown_1.1       fansi_0.4.2        highr_0.8         
    +  [29] Rcpp_1.0.6         scales_1.1.1       jsonlite_1.7.2     farver_2.1.0      
    +  [33] distill_1.2        png_0.1-7          digest_0.6.27      stringi_1.6.2     
    +  [37] grid_4.1.0         cli_3.0.1          tools_4.1.0        magrittr_2.0.1    
    +  [41] sass_0.4.0         tibble_3.1.2       crayon_1.4.1       pkgconfig_2.0.3   
    +  [45] downlit_0.2.1      ellipsis_0.3.2     xml2_1.3.2         data.table_1.14.0 
    +  [49] assertthat_0.2.1   rmarkdown_2.8      rstudioapi_0.13    R6_2.5.0          
    +  [53] compiler_4.1.0
    +
    +
    +
    +
    +
    +
      +
    1. And I can also personally attest that I used to use them until {ragg} was developed, and I never loaded these packages since. But this isn’t a value judgment - if these packages continue to work for you, then great! But do know that there are some known issues with reliability (though to be fair, {extrafont} and {showtext} were one of the first attempts at solving the font rendering issue in R and they’ve actually done a great job over the years!).↩︎

    2. +
    3. In fact, text rendering as a whole is an incredibly complicated task. Check out Text Rendering Hates You for a fun and informative read.↩︎

    4. +
    5. I’m focusing on outputing to bitmap (e.g., .png, .jpeg, .tiff). For other formats like SVG (which I often default to for online material), you can use svglite - read more on the package website.↩︎

    6. +
    7. Check out the discussion on this issue and this commit. There’s also been some talk of making AGG the default renderer, though I don’t know if that’s been settled.↩︎

    8. +
    9. These are used to calculate DPI (dots per inch). Resolution is in pixels, so res=150 and units="inch" is the same as dpi=150. {ragg} devices don’t have a dpi argument like the default device, so you have to specify both resolution and units.↩︎

    10. +
    11. in Windows 10, for example, you have to drag and drop fonts onto the “Fonts” section of Settings↩︎

    12. +
    13. Variable fonts are hit-or-miss because while {ragg} and {systemfonts} do support some variable font features (see the section on Advanced font features), “variable” can mean many different things, some of which are not supported (e.g., variable width). If you install a variable font, it might render with {ragg} but you’re unlikely to be able to tweak its parameters (like change the weight, for example).↩︎

    14. +
    15. In my experience, though, static fonts tend to be .ttf and variable fonts tend to be .otf.↩︎

    16. +
    17. “You can use them freely in your products & projects - print or digital, commercial or otherwise. However, you can’t sell the fonts on their own.”↩︎

    18. +
    19. Again, YMMV, but myself and a couple other folks I’ve talked to share this.↩︎

    20. +
    21. Technically, it defaults to fontface = "plain" which is the same thing, but {systemfonts} and (also probably your OS) calls it the “Regular” style↩︎

    22. +
    23. In case you’re wondering, it still errors with “solid”, no caps.↩︎

    24. +
    25. options(error = recover) is your friend! And remember to set options(error = NULL) back once you’re done!↩︎

    26. +
    27. You might wonder: what’s the {grid} package doing here? Well, {grid} is kinda the “engine” for {ggplot2} that handles the actual “drawing to the canvas”, which is why it’s relevant here. For example, geom_text() returns a Graphical object (“Grob”), specifically grid::textGrob(), that inherits arguments like family and fontface (which are in turn passed into grid::gpar(), where gpar stands for graphical parameters).↩︎

    28. +
    29. The same font file also registered as the Bold, Italic, and Bold Italic styles of the family as well, which is what happens by default if you only supply the plain argument to register_font().↩︎

    30. +
    31. Borrowing terminology from tidyr::hoist(), the under-appreciated beast of list-column workflows↩︎

    32. +
    33. Regular as “plain”, Bold as “bold”, Italic as “italic”, and Bold Italic as “bold.italic”.↩︎

    34. +
    35. Also check out the related “pnum” (proportional numbers) and “tnum” (tabular numbers) features.↩︎

    36. +
    37. check the help page ?systemfonts::font_feature for details.↩︎

    38. +
    39. Another solution would be to use the small-cap variant (the “smcp” feature) for “une”.↩︎

    40. +
    41. But this also means that not all fonts support “ordn”, while <sup> is always available.↩︎

    42. +
    43. But not all colored fonts, in my experience.↩︎

    44. +
    45. The colors are fixed though - they come colored in black and filled in grey.↩︎

    46. +
    +
    + + + +
    + +
    +
    + + + + + +
    + + + + + + + + + + + diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/preview.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/preview.png new file mode 100644 index 00000000..30e1cbda Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/preview.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-black-italic-lining-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-black-italic-lining-1.png new file mode 100644 index 00000000..87ff8155 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-black-italic-lining-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-lining-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-lining-1.png new file mode 100644 index 00000000..06faa579 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-lining-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-mixed-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-mixed-1.png new file mode 100644 index 00000000..2ac6717a Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-mixed-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-numbers-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-numbers-1.png new file mode 100644 index 00000000..53eacda3 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-numbers-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-allcap-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-allcap-1.png new file mode 100644 index 00000000..2070c74e Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-allcap-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-bad-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-bad-1.png new file mode 100644 index 00000000..21245d58 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-ordn-bad-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1..png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1..png new file mode 100644 index 00000000..9ac01872 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1..png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1.png new file mode 100644 index 00000000..7792c17a Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plot-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-1.png new file mode 100644 index 00000000..a2f7e68b Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-10.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-10.png new file mode 100644 index 00000000..b0c1c545 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-10.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-11.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-11.png new file mode 100644 index 00000000..65dc4d2b Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-11.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-12.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-12.png new file mode 100644 index 00000000..9bd70058 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-12.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-2.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-2.png new file mode 100644 index 00000000..025b69ed Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-2.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-3.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-3.png new file mode 100644 index 00000000..d9a2c85e Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-3.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-4.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-4.png new file mode 100644 index 00000000..7cd78950 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-4.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-5.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-5.png new file mode 100644 index 00000000..d78b31ee Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-5.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-6.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-6.png new file mode 100644 index 00000000..a4a1d7bd Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-6.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-7.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-7.png new file mode 100644 index 00000000..55f62d04 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-7.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-8.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-8.png new file mode 100644 index 00000000..41fc963b Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-8.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-9.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-9.png new file mode 100644 index 00000000..6b7be895 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-plots-9.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-pre-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-pre-1.png new file mode 100644 index 00000000..4dc3f49d Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/alegreya-pre-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1..png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1..png new file mode 100644 index 00000000..9ac01872 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1..png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1.png new file mode 100644 index 00000000..36d04172 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-fail-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1..png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1..png new file mode 100644 index 00000000..9ac01872 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1..png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1.png new file mode 100644 index 00000000..b83e996a Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2..png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2..png new file mode 100644 index 00000000..9ac01872 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2..png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2.png new file mode 100644 index 00000000..947068b8 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/fa-success-2.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/mash-up-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/mash-up-1.png new file mode 100644 index 00000000..323180ec Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/mash-up-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-fail-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-fail-1.png new file mode 100644 index 00000000..4dc3f49d Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-fail-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-success-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-success-1.png new file mode 100644 index 00000000..4d66c270 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/solid-success-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-10-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-10-1.png new file mode 100644 index 00000000..eca6bb30 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-10-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-11-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-11-1.png new file mode 100644 index 00000000..ea0a04e1 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-11-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1..png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1..png new file mode 100644 index 00000000..9ac01872 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1..png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1.png new file mode 100644 index 00000000..36d04172 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-4-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-5-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-5-1.png new file mode 100644 index 00000000..dd33e6b0 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-5-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-6-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-6-1.png new file mode 100644 index 00000000..dd33e6b0 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-6-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-7-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-7-1.png new file mode 100644 index 00000000..2e59320b Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-7-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-8-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-8-1.png new file mode 100644 index 00000000..028da630 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-8-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-9-1.png b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-9-1.png new file mode 100644 index 00000000..028da630 Binary files /dev/null and b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/figure-html5/unnamed-chunk-9-1.png differ diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.css b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.css new file mode 100644 index 00000000..7436b609 --- /dev/null +++ b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.css @@ -0,0 +1,112 @@ +/* prefixed by https://autoprefixer.github.io (PostCSS: v7.0.23, autoprefixer: v9.7.3) */ + +.panelset { + width: 100%; + position: relative; + --panel-tabs-border-bottom: #ddd; + --panel-tab-foreground: currentColor; + --panel-tab-background: unset; + --panel-tab-active-foreground: currentColor; + --panel-tab-active-background: unset; + --panel-tab-hover-foreground: currentColor; + --panel-tab-hover-background: unset; + --panel-tab-active-border-color: currentColor; + --panel-tab-hover-border-color: currentColor; + --panel-tab-inactive-opacity: 0.5; + --panel-tab-font-family: inherit; +} + +.panelset * { + box-sizing: border-box; +} + +.panelset .panel-tabs { + display: -webkit-box; + display: flex; + flex-wrap: wrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + flex-direction: row; + -webkit-box-pack: start; + justify-content: start; + -webkit-box-align: center; + align-items: center; + overflow-y: visible; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding: 0 0 2px 0; + box-shadow: inset 0 -2px 0px var(--panel-tabs-border-bottom); +} + +.panelset .panel-tabs * { + -webkit-transition: opacity 0.5s ease; + transition: opacity 0.5s ease; +} + +.panelset .panel-tabs .panel-tab { + min-height: 50px; + display: -webkit-box; + display: flex; + -webkit-box-pack: center; + justify-content: center; + -webkit-box-align: center; + align-items: center; + padding: 0.5em 1em; + font-family: var(--panel-tab-font-family); + opacity: var(--panel-tab-inactive-opacity); + border-top: 2px solid transparent; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + color: var(--panel-tab-foreground); + background-color: var(--panel-tab-background); + list-style: none; + z-index: 5; +} + +.panelset .panel-tabs .panel-tab > a { + color: currentColor; + text-decoration: none; + border: none; +} + +.panelset .panel-tabs .panel-tab > a:focus { + outline: none; + text-decoration: none; + border: none; +} + +.panelset .panel-tabs .panel-tab > a:hover { + text-decoration: none; + border: none; +} + +.panelset .panel-tabs .panel-tab:hover { + border-bottom-color: var(--panel-tab-hover-border-color); + color: var(--panel-tab-hover-foreground); + background-color: var(--panel-tab-hover-background); + opacity: 1; + cursor: pointer; + z-index: 10; +} + +.panelset .panel-tabs .panel-tab:focus { + outline: none; + color: var(--panel-tab-hover-foreground); + border-bottom-color: var(--panel-tab-hover-border-color); + background-color: var(--panel-tab-hover-background); +} + +.panelset .panel-tabs .panel-tab.panel-tab-active { + border-top-color: var(--panel-tab-active-border-color); + color: var(--panel-tab-active-foreground); + background-color: var(--panel-tab-active-background); + opacity: 1; +} + +.panelset .panel { + display: none; +} + +.panelset .panel-active { + display: block; +} diff --git a/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.js b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.js new file mode 100644 index 00000000..80e773ca --- /dev/null +++ b/docs/posts/2021-06-24-setting-up-and-debugging-custom-fonts/setting-up-and-debugging-custom-fonts_files/panelset-0.2.6/panelset.js @@ -0,0 +1,324 @@ +/* global slideshow */ +(function () { + const ready = function (fn) { + /* MIT License Copyright (c) 2016 Nuclei */ + /* https://github.com/nuclei/readyjs */ + const completed = () => { + document.removeEventListener('DOMContentLoaded', completed) + window.removeEventListener('load', completed) + fn() + } + if (document.readyState !== 'loading') { + setTimeout(fn) + } else { + document.addEventListener('DOMContentLoaded', completed) + window.addEventListener('load', completed) + } + } + + ready(function () { + [...document.querySelectorAll('.panel-name')] + .map(el => el.textContent.trim()) + + const panelIds = {} + + const uniquePanelId = (name) => { + name = encodeURIComponent(name.toLowerCase().replace(/[\s]/g, '-')) + if (Object.keys(panelIds).includes(name)) { + name += ++panelIds[name] + } else { + panelIds[name] = 1 + } + return name + } + + const identifyPanelName = (item) => { + let name = 'Panel' + + // If the item doesn't have a parent element, then we've already processed + // it, probably because we're in an Rmd, and it's been removed from the DOM + if (!item.parentElement) { + return + } + + // In R Markdown when header-attrs.js is present, we may have found a + // section header but the class attributes won't be duplicated on the tag + if ( + (item.tagName === 'SECTION' || item.classList.contains('section')) && + /^H[1-6]/.test(item.children[0].tagName) + ) { + name = item.children[0].textContent + item.classList.remove('panel-name') + item.removeChild(item.children[0]) + return name + } + + const nameDiv = item.querySelector('.panel-name') + if (!nameDiv) return name + + // In remarkjs the .panel-name span might be in a paragraph tag + // and if the

    is empty, we'll remove it + if ( + nameDiv.tagName === 'SPAN' && + nameDiv.parentNode.tagName === 'P' && + nameDiv.textContent === nameDiv.parentNode.textContent + ) { + name = nameDiv.textContent + item.removeChild(nameDiv.parentNode) + return name + } + + // If none of the above, remove the nameDiv and return the name + name = nameDiv.textContent + nameDiv.parentNode.removeChild(nameDiv) + return name + } + + const processPanelItem = (item) => { + const name = identifyPanelName(item) + if (!name) { + return null + } + return { name, content: item.children, id: uniquePanelId(name) } + } + + const getCurrentPanelFromUrl = (panelset) => { + const params = new URLSearchParams(window.location.search) + return params.get(panelset) + } + + const reflowPanelSet = (panels, idx) => { + const res = document.createElement('div') + res.className = 'panelset' + res.id = 'panelset' + (idx > 0 ? idx : '') + const panelSelected = getCurrentPanelFromUrl(res.id) + + // create header row + const headerRow = document.createElement('ul') + headerRow.className = 'panel-tabs' + headerRow.setAttribute('role', 'tablist') + panels + .map((p, idx) => { + const panelHeaderItem = document.createElement('li') + panelHeaderItem.className = 'panel-tab' + panelHeaderItem.setAttribute('role', 'tab') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + if (thisPanelIsActive) { + panelHeaderItem.classList.add('panel-tab-active') + panelHeaderItem.setAttribute('aria-selected', true) + } + panelHeaderItem.tabIndex = 0 + panelHeaderItem.id = res.id + '_' + p.id // #panelsetid_panelid + + const panelHeaderLink = document.createElement('a') + panelHeaderLink.href = '?' + res.id + '=' + p.id + '#' + panelHeaderItem.id + panelHeaderLink.setAttribute('onclick', 'return false;') + panelHeaderLink.tabIndex = -1 // list item is tabable, not link + panelHeaderLink.innerHTML = p.name + panelHeaderLink.setAttribute('aria-controls', p.id) + + panelHeaderItem.appendChild(panelHeaderLink) + return panelHeaderItem + }) + .forEach(el => headerRow.appendChild(el)) + + res.appendChild(headerRow) + + panels + .map((p, idx) => { + const panelContent = document.createElement('section') + panelContent.className = 'panel' + panelContent.setAttribute('role', 'tabpanel') + const thisPanelIsActive = panelSelected ? panelSelected === p.id : idx === 0 + panelContent.classList.toggle('panel-active', thisPanelIsActive) + panelContent.id = p.id + panelContent.setAttribute('aria-labelledby', p.id) + Array.from(p.content).forEach(el => panelContent.appendChild(el)) + return panelContent + }) + .forEach(el => res.appendChild(el)) + + return res + } + + /* + * Update selected panel for panelset or delete panelset from query string + * + * @param panelset Panelset ID to update in the search params + * @param panel Panel ID of selected panel in panelset, or null to delete from search params + * @param params Current params object, or params from window.location.search + */ + function updateSearchParams (panelset, panel, params = new URLSearchParams(window.location.search)) { + if (panel) { + params.set(panelset, panel) + } else { + params.delete(panelset) + } + return params + } + + /* + * Update the URL to match params + */ + const updateUrl = (params) => { + if (typeof params === 'undefined') return + params = params.toString() ? ('?' + params.toString()) : '' + const { pathname, hash } = window.location + const uri = pathname + params + hash + window.history.replaceState(uri, '', uri) + } + + const togglePanel = (clicked) => { + if (clicked.nodeName.toUpperCase() === 'A') { + clicked = clicked.parentElement + } + if (!clicked.classList.contains('panel-tab')) return + if (clicked.classList.contains('panel-tab-active')) return + + const tabs = clicked.parentNode + .querySelectorAll('.panel-tab') + const panels = clicked.parentNode.parentNode + .querySelectorAll('.panel') + const panelTabClicked = clicked.children[0].getAttribute('aria-controls') + const panelClicked = clicked.parentNode.parentNode.id + + Array.from(tabs) + .forEach(t => { + t.classList.remove('panel-tab-active') + t.removeAttribute('aria-selected') + }) + Array.from(panels) + .forEach(p => { + const active = p.id === panelTabClicked + p.classList.toggle('panel-active', active) + // make inactive panels inaccessible by keyboard navigation + if (active) { + p.removeAttribute('tabIndex') + p.removeAttribute('aria-hidden') + } else { + p.setAttribute('tabIndex', -1) + p.setAttribute('aria-hidden', true) + } + }) + + clicked.classList.add('panel-tab-active') + clicked.setAttribute('aria-selected', true) + + // emit window resize event to trick html widgets into fitting to the panel width + window.dispatchEvent(new Event('resize')) + + // update query string + const params = updateSearchParams(panelClicked, panelTabClicked) + updateUrl(params) + } + + const initPanelSet = (panelset, idx) => { + let panels = Array.from(panelset.querySelectorAll('.panel')) + if (!panels.length && panelset.matches('.section[class*="level"]')) { + // we're in tabset-alike R Markdown + const panelsetLevel = [...panelset.classList] + .filter(s => s.match(/^level/))[0] + .replace('level', '') + + // move children that aren't inside a section up above the panelset + Array.from(panelset.children).forEach(function (el) { + if (el.matches('div.section[class*="level"]')) return + panelset.parentElement.insertBefore(el, panelset) + }) + + // panels are all .sections with .level + const panelLevel = +panelsetLevel + 1 + panels = Array.from(panelset.querySelectorAll(`.section.level${panelLevel}`)) + } + + if (!panels.length) return + + const contents = panels.map(processPanelItem).filter(o => o !== null) + const newPanelSet = reflowPanelSet(contents, idx) + panelset.parentNode.insertBefore(newPanelSet, panelset) + panelset.parentNode.removeChild(panelset) + + // click and touch events + const panelTabs = newPanelSet.querySelector('.panel-tabs'); + ['click', 'touchend'].forEach(eventType => { + panelTabs.addEventListener(eventType, function (ev) { + togglePanel(ev.target) + ev.stopPropagation() + }) + }) + panelTabs.addEventListener('touchmove', function (ev) { + ev.preventDefault() + }) + + // key events + newPanelSet + .querySelector('.panel-tabs') + .addEventListener('keydown', (ev) => { + const self = ev.currentTarget.querySelector('.panel-tab-active') + if (ev.code === 'Space' || ev.code === 'Enter') { + togglePanel(ev.target) + ev.stopPropagation() + } else if (ev.code === 'ArrowLeft' && self.previousSibling) { + togglePanel(self.previousSibling) + self.previousSibling.focus() + ev.stopPropagation() + } else if (ev.code === 'ArrowRight' && self.nextSibling) { + togglePanel(self.nextSibling) + self.nextSibling.focus() + ev.stopPropagation() + } + }) + + return panels + } + + // initialize panels + Array.from(document.querySelectorAll('.panelset')).map(initPanelSet) + + if (typeof slideshow !== 'undefined') { + const getVisibleActivePanelInfo = () => { + const slidePanels = document.querySelectorAll('.remark-visible .panel-tab-active') + + if (!slidePanels.length) return null + + return slidePanels.map(panel => { + return { + panel, + panelId: panel.children[0].getAttribute('aria-controls'), + panelSetId: panel.parentNode.parentNode.id + } + }) + } + + slideshow.on('hideSlide', slide => { + // clear focus if we had a panel-tab selected + document.activeElement.blur() + + // clear search query for panelsets in current slide + const params = [...document.querySelectorAll('.remark-visible .panelset')] + .reduce(function (params, panelset) { + return updateSearchParams(panelset.id, null, params) + }, new URLSearchParams(window.location.search)) + + updateUrl(params) + }) + + slideshow.on('afterShowSlide', slide => { + const slidePanels = getVisibleActivePanelInfo() + + if (slidePanels) { + // only first panel gets focus + slidePanels[0].panel.focus() + // but still update the url to reflect all active panels + const params = slidePanels.reduce( + function (params, { panelId, panelSetId }) { + return updateSearchParams(panelSetId, panelId, params) + }, + new URLSearchParams(window.location.search) + ) + updateUrl(params) + } + }) + } + }) +})() diff --git a/docs/posts/posts.json b/docs/posts/posts.json new file mode 100644 index 00000000..ada94435 --- /dev/null +++ b/docs/posts/posts.json @@ -0,0 +1,531 @@ +[ + { + "path": "posts/2021-06-24-setting-up-and-debugging-custom-fonts/", + "title": "Setting up and debugging custom fonts", + "description": "A practical introduction to all (new) things font in R", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2021-06-24", + "categories": [ + "data visualization", + "ggplot2", + "typography", + "tutorial" + ], + "contents": "\r\n\r\nContents\r\nIntroduction\r\nSetting up {ragg}\r\n1. Rendering in RStudio plot pane\r\n2. Saving as an external file\r\n3. Rmarkdown\r\n4. Shiny\r\n\r\nInstalling custom fonts\r\nFinding the right file\r\nChecking that a font is installed and available\r\n\r\nDebugging custom fonts\r\nHoisting font styles\r\nAdvanced font features\r\nLining\r\nOrdinals\r\n\r\nUsecases\r\nA mash-up\r\nIcon fonts\r\nMore by others\r\n\r\nSession info\r\n\r\n\r\nThis blog post was featured in the R Weekly highlights podcast! Thanks to the R Weekly team for the comprehensive review!\r\nAn important point of clarification (30/07/2021): Many people are familiar with {showtext} and {extrafont}, and may even have existing workflows centered around those packages. In this blog post, there is no “installing” of fonts of any sort within the R session. The magic here is that {ragg} is designed to directly access the fonts installed on your system (with some caveats as described in detail later). This issue of the graphics device is independent of the kind of things that {showtext} and {extrafont} does, which is why they’re not relevant here.\r\ntl;dr: don’t use {showtext} and don’t use {extrafont} when following the workflow described in this blog post!1\r\n\r\nIntroduction\r\nGetting custom fonts to work in R has historically been pretty difficult.2 At a high level, it involves the non-trivial task of unifying the graphics device, the operating system, and text rendering, (and also in our case, R!) to seamlessly work with each other.\r\nLuckily for us in 2021, we have an amazing solution to this problem thanks to recent developments in the {ragg}, {systemfonts}, and {textshaping} packages by RStudio. This is great news because a lot of the work for getting custom fonts to work in R is already done for us!\r\nIn this blog post, I’ll start with the basics of setting up custom fonts followed by a walkthrough of the font debugging workflow, concluding with some practical use-cases that can spice up your typography game for data viz. \r\nSetting up {ragg}\r\nThe first thing you should do, if you haven’t already, is to install {ragg}, {systemfonts}, and {textshaping}.\r\n\r\n\r\ninstall.packages('ragg')\r\ninstall.packages('systemfonts')\r\ninstall.packages('textshaping')\r\n\r\n\r\n\r\nNext, we want to make sure that whenever we output a plot3, we do so using the AGG graphics device (that’s the “agg” part of “ragg”).\r\nThere are at least four places where this is relevant:\r\n1. Rendering in RStudio plot pane\r\nFor RStudio >= 1.4, go to Tools > Global Options > General > Graphics and set the Backend to AGG.\r\n\r\n\r\n\r\nFigure 1: Where to set AGG as the graphic device for RStudio - image from https://ragg.r-lib.org\r\n\r\n\r\n\r\n2. Saving as an external file\r\nFor bitmap output, use any of the ragg::agg_*() function to render plots using the AGG device.\r\n\r\n\r\n# Set output path\r\npngfile <- here::here(\"img\", \"my_plot.png\")\r\n# Initialize device\r\nragg::agg_png(\r\n pngfile, width = 10, height = 6, units = \"in\",\r\n res = 300, scaling = 3\r\n)\r\n# Plot\r\nplot(hist(mtcars$mpg))\r\n# Close device\r\ninvisible(dev.off())\r\n\r\n\r\n\r\nFor ggplot2 figures: as of the new ggplot2 v3.3.4 release (released 06-16-2021), ggsave() automatically defaults to rendering the output using agg_*() devices!\r\n\r\nOld disclaimer for {ggplot2} < v.3.3.4\r\n\r\nThis long-winded way works for any plot, but if you use {ggplot2} and ggplot2::ggsave() a lot, you might wonder whether you can just pass in ragg::agg_png() into the device argument and specify the arguments in ggsave() instead. This turns out to actually not be so straightforward, but will likely be patched in the next update (v3.3.4?). 4\r\n3. Rmarkdown\r\nPass in a {ragg} device has res and units specified to the dev argument of knitr::chunk_opts$set() at the top of the script.5\r\n\r\n\r\nragg_png = function(..., res = 150) {\r\n ragg::agg_png(..., res = res, units = \"in\")\r\n}\r\nopts_chunk$set(dev = \"ragg_png\")\r\n\r\n\r\n\r\n4. Shiny\r\nSimply set options(shiny.useragg = TRUE) before rendering. Also check out the {thematic} package for importing/using custom fonts in shiny plot outputs.\r\nInstalling custom fonts\r\nNow that you have {ragg} and {systemfonts} installed, take it for a spin with a custom font! When you’re rendering plots using {ragg}, custom fonts should just work as long as you have them installed on your local machine.\r\nIf you haven’t really worked with custom fonts before, “installing a custom font” simply means finding the font file on the internet, downloading it, and drag-and-drop into a special folder on your local machine. It’s something like Network/Library/Fonts for Macs and Microsoft/Windows/Fonts for Windows. There can actually be a bit more to this process6, so make sure to google and check the process for installing fonts on your machine.\r\nFinding the right file\r\nFont files come in many forms. In general, fonts files that match these two criteria tend to work the best:\r\nFonts in .otf (OpenType Font) or .ttf (TrueType Font) formats. These are font formats that are installable on your local machine. You want to avoid other formats like .woff or .woff2, for example, which are designed for use for the web. In theory both .otf and .ttf should work with {ragg}, though I’ve sometimes had trouble with .otf. In those cases, I simply converted the .otf font file to .ttf before installing it, using free online conversion tools that you can easily find on Google. I’m of course glossing over the details here and I’m hardly an expert, but you can read more about TrueType and OpenType formats here.\r\nStatic fonts. In static fonts, each member of the family has their own set of glyphs (i.e., there is a font file for each style). This is in contrast to variable fonts, where you have a single font file which can take the form of multiple styles (either by having many sets of glyphs or variable parameters).7 To illustrate, look at the difference between the static (top) vs. variable (bottom) files for the Alegreya family.\r\n\r\n\r\n\r\nFigure 2: Static font files for Alegreya\r\n\r\n\r\n\r\n\r\n\r\n\r\nFigure 3: Variable font files for Alegreya\r\n\r\n\r\n\r\nWe see that static fonts are differentiated from variable fonts by having a distinct file for each style, like Alegreya-Black.ttf. On the other hand, variable fonts usually say “variable” somewhere in the file name, and are slightly larger in size than any individual static member. Note that not all fonts have both static and variable files, and not all static font files are .ttf (there can be static .otf and variable .ttf files).8\r\nThe above two images show the contents of the .zip file that you’d get if you went to Google Fonts (an awesome repository of free and open-source professional fonts) and clicked the Download family button on the page for Alegreya. If you want to use the Alegreya font family (Open Font License9) in R, then you simply drag-and-drop all the static font files in /static into your system’s font folder (or in Settings > Fonts for Windows 10).\r\nChecking that a font is installed and available\r\nOnce you install a custom font on your system, it should also be available elsewhere locally on your machine. For example, I can use Alegreya in Microsoft Word after I download it (this is actually my first go-to sanity check).\r\n\r\n\r\n\r\nFigure 4: Alegreya in Microsoft Word\r\n\r\n\r\n\r\nAnd by extension Alegreya should now be available for figures rendered with {ragg}. Let’s try using Alegreya in ggplot by passing it to the family argument of geom_text()\r\n\r\n\r\nlibrary(ggplot2)\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"The Alegreya font\"),\r\n size = 18, family = \"Alegreya\"\r\n )\r\n\r\n\r\n\r\n\r\nIt just works!\r\nMore specifically, it works because Alegreya is visible to {systemfonts}, which handles text rendering for {ragg}. If we filter list of fonts from systemfonts::system_fonts(), we indeed find the 12 styles of Alegreya from the static .ttf files that we installed!\r\n\r\n\r\nlibrary(systemfonts)\r\nlibrary(dplyr)\r\nlibrary(stringr)\r\n\r\nsystem_fonts() %>% \r\n filter(family == \"Alegreya\") %>% \r\n transmute(\r\n family, style,\r\n file = str_extract(path, \"[\\\\w-]+\\\\.ttf$\")\r\n )\r\n\r\n\r\n # A tibble: 12 x 3\r\n family style file \r\n \r\n 1 Alegreya Black Italic Alegreya-BlackItalic.ttf \r\n 2 Alegreya Bold Alegreya-Bold.ttf \r\n 3 Alegreya Bold Italic Alegreya-BoldItalic.ttf \r\n 4 Alegreya ExtraBold Alegreya-ExtraBold.ttf \r\n 5 Alegreya ExtraBold Italic Alegreya-ExtraBoldItalic.ttf\r\n 6 Alegreya Italic Alegreya-Italic.ttf \r\n 7 Alegreya Medium Alegreya-Medium.ttf \r\n 8 Alegreya Medium Italic Alegreya-MediumItalic.ttf \r\n 9 Alegreya Regular Alegreya-Regular.ttf \r\n 10 Alegreya SemiBold Alegreya-SemiBold.ttf \r\n 11 Alegreya SemiBold Italic Alegreya-SemiBoldItalic.ttf \r\n 12 Alegreya Black Alegreya-Black.ttf\r\n\r\nDebugging custom fonts\r\nSo far we’ve seen that the workflow for setting up and installing fonts is pretty straightforward. But what do we do in times when things inevitable go wrong?\r\nConsider the case of using Font Awesome, an icon font that renders special character sequences as icon glyphs (check the Icon fonts section for more!). Font Awesome has a free version (CC-BY and SIL OFL license), and let’s say we want to use it for personal use for a TidyTuesday submission.\r\nThe first thing we do is locate the font file. Font Awesome is open source, and the free version (Font Awesome 5 Free) is updated on Github. The most recent release as of this blog post is v5.15.3. If you unzip the file, you’ll find .otf font files corresponding to the three variants available in the free version: Regular, Solid, and Brands.\r\n\r\n\r\n\r\nFigure 5: Font Awesome 5 files\r\n\r\n\r\n\r\nRemember how I said R tends to play nicer with .ttf than .otf fonts?10 Lets go ahead and convert the .otf files using an online converter, like https://convertio.co/otf-ttf. Now, with the three font files in .ttf format, follow the instructions for installing fonts on your OS.\r\nOnce Font Awesome is installed on our local machine, it should be visible to {systemfonts}, like this:\r\n\r\n\r\nsystem_fonts() %>% \r\n filter(str_detect(family, \"Font Awesome 5\")) %>% \r\n transmute(\r\n family, style,\r\n file = stringr::str_extract(path, \"[\\\\w-]+\\\\.ttf$\")\r\n )\r\n\r\n\r\n # A tibble: 3 x 3\r\n family style file \r\n \r\n 1 Font Awesome 5 Free Solid Font-Awesome-5-Free-Solid-900.ttf \r\n 2 Font Awesome 5 Brands Regular Font-Awesome-5-Brands-Regular-400.ttf\r\n 3 Font Awesome 5 Free Regular Font-Awesome-5-Free-Regular-400.ttf\r\n\r\nNow let’s try plotting some icons!\r\nWe see that we can render icons from the Regular variant (“clock”) and the Brands variant (“twitter”).\r\n\r\n\r\n# Left plot\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"clock\"),\r\n size = 50, family = \"Font Awesome 5 Free\"\r\n )\r\n\r\n# Right plot\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"twitter\"),\r\n size = 50, family = \"Font Awesome 5 Brands\"\r\n )\r\n\r\n\r\n\r\n\r\nBut what about rendering in the Solid variant? Font Awesome tells me that the Solid variant has a “cat” icon, so let’s try it.\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(aes(label = \"cat\"), size = 50, family = \"Font Awesome 5 Solid\")\r\n\r\n\r\n\r\n\r\nUh oh, that didn’t work. Well that’s because Solid is actually a style, not a family! If you go back to the output from system_fonts(), we see that Font Awesome actually consists of two font families: Font Awesome 5 Brands which has a “Regular” style, and Font Awesome 5 Free with a “Regular” style and a “Solid” style.\r\nThe structure is roughly like this:\r\n\r\n Font Awesome 5 Free\r\n |--- Regular\r\n |--- Solid\r\n Font Awesome 5 Brands\r\n |--- Regular\r\n\r\nIn geom_text(), the font style is set by the fontface argument. When we don’t specify fontface, such as in our working example for the clock and twitter icons, it defaults to the Regular style.11\r\nSo the solution to our problem is to put in fontface = \"Solid\", right…?\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"cat\"), size = 50,\r\n family = \"Font Awesome 5 Free\", fontface = \"solid\"\r\n )\r\n\r\n\r\n Error in FUN(X[[i]], ...): invalid fontface solid\r\n\r\nWell now it just errors!12 The issue here runs a bit deeper: if we track down the error,13 it takes us to a function inside grid::gpar() that validates fontface. 14 If we take a look at the code, we see that only a very few font styles are valid, and “solid” isn’t one of them.\r\n\r\n\r\nfunction (ch) \r\nswitch(ch, plain = 1L, bold = 2L, italic = , oblique = 3L, bold.italic = 4L, \r\n symbol = 5L, cyrillic = 5L, cyrillic.oblique = 6L, EUC = 7L, \r\n stop(\"invalid fontface \", ch))\r\n\r\n\r\n\r\nOkay, so then how can we ever access the Solid style of the Font Awesome 5 Free family? Luckily, there’s a solution: use systemfonts::register_font() to register the Solid style as the “plain” style of its own font family!\r\nWe can do this by passing in the name of the new font family in the name argument, and passing the path of the font file to the plain argument.\r\n\r\n\r\nfa_solid_path <- system_fonts() %>% \r\n filter(family == \"Font Awesome 5 Free\", style == \"Solid\") %>% \r\n pull(path)\r\n\r\nsystemfonts::register_font(\r\n name = \"Font Awesome 5 Free Solid\",\r\n plain = fa_solid_path\r\n)\r\n\r\n\r\n\r\nTo check if we were successful in registering this new font variant, we can call systemfonts::registry_fonts() which returns all registered custom fonts in the current session:\r\n\r\n\r\nsystemfonts::registry_fonts() %>% \r\n transmute(\r\n family, style,\r\n file = stringr::str_extract(path, \"[\\\\w-]+\\\\.ttf$\")\r\n )\r\n\r\n\r\n # A tibble: 4 x 3\r\n family style file \r\n \r\n 1 Font Awesome 5 Free Solid Regular Font-Awesome-5-Free-Solid-900.ttf\r\n 2 Font Awesome 5 Free Solid Bold Font-Awesome-5-Free-Solid-900.ttf\r\n 3 Font Awesome 5 Free Solid Italic Font-Awesome-5-Free-Solid-900.ttf\r\n 4 Font Awesome 5 Free Solid Bold Italic Font-Awesome-5-Free-Solid-900.ttf\r\n\r\nWe see that the Solid style is now available as the Regular (a.k.a. “plain”) style of its own font family: Font Awesome 5 Free Solid!15\r\nNow we’re back to our cat icon example. Again, because Font Awewsome says there’s a cat icon in the Solid style, we’d expect a cat icon if we render the text “cat” in the Solid style. Let’s set the family argument to our newly registered “Font Awesome 5 Free Solid” family and see what happens:\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(aes(label = \"cat\"), size = 50, family = \"Font Awesome 5 Free Solid\")\r\n\r\n\r\n\r\n\r\nThird time’s the charm !!!\r\nHoisting font styles\r\nHopefully the lesson is now clear: to make a custom font work in R, the font must be visible to systemfonts::system_fonts() in a style that is accessible to grid::gpar(). The nifty trick of registering an inaccessible style as the “plain” style of its own family can be extended and automated as a utility function that is called purely for this side effect. In my experimental package, I have very simple function called font_hoist() which “hoists”16 all styles of a family as the “plain”/Regular style of their own families. This way, you never have to worry about things going wrong in the fontface argument.\r\n\r\njunebug::font_hoist()\r\n\r\n\r\nfont_hoist <- function(family, silent = FALSE) {\r\n font_specs <- systemfonts::system_fonts() %>%\r\n dplyr::filter(family == .env[[\"family\"]]) %>%\r\n dplyr::mutate(family = paste(.data[[\"family\"]], .data[[\"style\"]])) %>%\r\n dplyr::select(plain = .data[[\"path\"]], name = .data[[\"family\"]])\r\n\r\n purrr::pwalk(as.list(font_specs), systemfonts::register_font)\r\n\r\n if (!silent) message(paste0(\"Hoisted \", nrow(font_specs), \" variants:\\n\",\r\n paste(font_specs$name, collapse = \"\\n\")))\r\n}\r\n\r\n\r\n\r\nLet’s apply this to our Alegreya family. As we saw earlier, it has 12 styles, but only 4 can be accessed by grid::gpar().17 But once we hoist the styles, we can access them all!\r\n\r\n\r\n# install_github(\"yjunechoe/junebug\")\r\njunebug::font_hoist(\"Alegreya\")\r\n\r\n\r\n Hoisted 12 variants:\r\n Alegreya Black Italic\r\n Alegreya Bold\r\n Alegreya Bold Italic\r\n Alegreya ExtraBold\r\n Alegreya ExtraBold Italic\r\n Alegreya Italic\r\n Alegreya Medium\r\n Alegreya Medium Italic\r\n Alegreya Regular\r\n Alegreya SemiBold\r\n Alegreya SemiBold Italic\r\n Alegreya Black\r\n\r\n\r\n\r\n# Grab the newly registered font families\r\nalegreya_styles <- systemfonts::registry_fonts() %>% \r\n filter(str_detect(family, \"Alegreya\"), style == \"Regular\") %>% \r\n pull(family)\r\n\r\n# Render a plot for all 12 styles\r\npurrr::walk(\r\n alegreya_styles,\r\n ~ print(ggplot(NULL, aes(0, 0)) +\r\n geom_text(aes(label = .x), size = 14, family = .x))\r\n)\r\n\r\n\r\n\r\n\r\nBut note that the registration of custom font variants is not persistent across sessions. If you restart R and run registry_fonts() again, it will return an empty data frame, indicating that you have no font variants registered. You have to register font variants for every session, which is why it’s nice to have the register_fonts() workflow wrapped into a function like font_hoist().\r\nAdvanced font features\r\nBut wait, that’s not all!\r\nMany modern professional fonts come with OpenType features, which mostly consist of stylistic parameters that can be turned on-and-off for a font. Note that despite being called “OpenType” features, it’s not something unique to .otf font formats. TrueType fonts (.ttf) can have OpenType features as well. For a fuller picture, you can check out the full list of registered features and this article with visual examples for commonly used features.\r\nIt looks overwhelming but only a handful are relevant for data visualization. I’ll showcase two features here: lining and ordinals.\r\nLining\r\nOne of the most practical font features is lining, also called \"lnum\" (the four-letter feature tag), where all numbers share the same height and baseline.18\r\nLet’s use our Alegreya font as an example again. By default, Alegreya has what are called “old style” numbers, where number glyphs have ascending and descending strokes which can make a string of numbers look unbalanced. Notice how the digits share different baselines here:\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"123456789\"),\r\n size = 35, family = \"Alegreya\"\r\n )\r\n\r\n\r\n\r\n\r\nLuckily, Alegreya supports the “lining” feature. We know this because the get_font_features() function from the {textshaping} package returns a lists of OpenType features supported by Alegreya, one of which is “lnum”.\r\n\r\n\r\nlibrary(textshaping)\r\nget_font_features(\"Alegreya\")\r\n\r\n\r\n [[1]]\r\n [1] \"cpsp\" \"kern\" \"mark\" \"mkmk\" \"aalt\" \"c2sc\" \"case\" \"ccmp\" \"dlig\" \"dnom\"\r\n [11] \"frac\" \"liga\" \"lnum\" \"locl\" \"numr\" \"onum\" \"ordn\" \"pnum\" \"sinf\" \"smcp\"\r\n [21] \"ss01\" \"ss02\" \"ss03\" \"ss04\" \"ss05\" \"subs\" \"sups\" \"tnum\"\r\n\r\nTo access the lining feature, we can use the systemfonts::register_variant() function, which works similarly to systemfonts::register_font(). The former is simply a wrapper around the latter, and we use it here for convenience because “Alegreya” (as in, the default Regular style) is already accessible without us having to point to the font file.\r\nTo turn the lining feature on, we need to set the features argument of register_variant() using the helper function systemfonts::font_feature(). The full code looks like this:\r\n\r\n\r\nsystemfonts::register_variant(\r\n name = \"Alegreya-lining\",\r\n family = \"Alegreya\",\r\n features = systemfonts::font_feature(numbers = \"lining\")\r\n)\r\n\r\n\r\n\r\nAnd again, we can see if the font variant was successfully registered by checking registry_fonts():\r\n\r\n\r\nregistry_fonts() %>% \r\n filter(family == \"Alegreya-lining\", style == \"Regular\") %>% \r\n transmute(\r\n family, style,\r\n features = names(features[[1]])\r\n )\r\n\r\n\r\n # A tibble: 1 x 3\r\n family style features\r\n \r\n 1 Alegreya-lining Regular lnum\r\n\r\nAnd that’s it! Let’s try rendering the numbers again with the original “Alegreya” font (top) and the new “Alegreya-lining” variant (bottom):\r\n\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 1, label = \"123456789\"),\r\n size = 35, family = \"Alegreya\") +\r\n geom_text(\r\n aes(0, 0, label = \"123456789\"),\r\n size = 35, family = \"Alegreya-lining\"\r\n ) +\r\n scale_y_continuous(expand = expansion(add = 0.5))\r\n\r\n\r\n\r\n\r\nA subtle but noticeable difference!\r\nIf we want a font variant to have a mix of different style and OpenType features, we have to go back to register_font() (where we register styles as their own families by pointing to the files) and set the features argument there.\r\n\r\n\r\n# Get file path\r\nAlegreyaBlackItalic_path <- system_fonts() %>% \r\n filter(family == \"Alegreya\", style == \"Black Italic\") %>% \r\n pull(path)\r\n\r\n# Register variant\r\nregister_font(\r\n name = \"Alegreya Black Italic-lining\",\r\n plain = AlegreyaBlackItalic_path,\r\n features = font_feature(numbers = \"lining\")\r\n)\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 1, label = \"123456789\"),\r\n size = 35, family = \"Alegreya Black Italic\"\r\n ) +\r\n geom_text(\r\n aes(0, 0, label = \"123456789\"),\r\n size = 35, family = \"Alegreya Black Italic-lining\"\r\n ) +\r\n scale_y_continuous(expand = expansion(add = 0.5))\r\n\r\n\r\n\r\n\r\nOrdinals\r\nOrdinals (or “ordn”) is a font feature which works almost like a superscript. It targets all lower case letters, and is intended for formatting ordinals like 1st, 2nd, 3rd.\r\nLet’s try it out!\r\nFirst, we check that “ordn” is supported for Alegreya:\r\n\r\n\r\n\"ordn\" %in% unlist(get_font_features(\"Alegreya\"))\r\n\r\n\r\n [1] TRUE\r\n\r\nThen, we register the ordinal variant. Note that “ordn” is not built-in as an option for the letters argument of font_features(), unlike “lnum” which is a built-in option for the numbers argument.19 Therefore, we have to set the “ordn” feature inside the ... of font_feature() with \"ordn\" = TRUE. And let’s also simultaneously turn on the lining feature from before as well.\r\n\r\n\r\n# Register variant\r\nregister_variant(\r\n name = \"Alegreya-lnum_ordn\",\r\n family = \"Alegreya\",\r\n features = font_feature(numbers = \"lining\", \"ordn\" = TRUE)\r\n)\r\n\r\n# Double check registration\r\nregistry_fonts() %>% \r\n filter(family == \"Alegreya-lnum_ordn\", style == \"Regular\") %>% \r\n pull(features)\r\n\r\n\r\n [[1]]\r\n ordn lnum \r\n 1 1\r\n\r\n\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 1, label = \"1st 2nd 3rd 4th\"),\r\n size = 20, family = \"Alegreya\"\r\n ) +\r\n geom_text(\r\n aes(0, 0, label = \"1st 2nd 3rd 4th\"),\r\n size = 20, family = \"Alegreya-lnum_ordn\"\r\n ) +\r\n scale_y_continuous(expand = expansion(add = 0.5))\r\n\r\n\r\n\r\n\r\nAgain, it’s important to note that this targets all lower case letters. So something like this renders awkwardly:\r\n\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 0, label = \"June 16th 2021\"),\r\n size = 20, family = \"Alegreya-lnum_ordn\"\r\n )\r\n\r\n\r\n\r\n\r\nWe could turn “June” into all caps, but that still looks pretty ugly:\r\n\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 0, label = \"JUNE 16th 2021\"),\r\n size = 20, family = \"Alegreya-lnum_ordn\"\r\n )\r\n\r\n\r\n\r\n\r\nOne solution is to render the month in the Regular style and the rest in the ordinal variant.20 We can combine text in multiple fonts in-line with html syntax supported by geom_richtext() from {ggtext}. If you’re already familiar with {ggtext}, this example shows that it works the same for registered custom font variants!\r\n\r\n\r\nlibrary(ggtext)\r\n\r\nformatted_date <- \"16th 2021<\/span>\"\r\n\r\nggplot(NULL) +\r\n geom_richtext(\r\n aes(0, 0, label = paste(\"June\", formatted_date)),\r\n size = 20, family = \"Alegreya\",\r\n fill = NA, label.color = NA\r\n )\r\n\r\n\r\n\r\n\r\nWhat’s extra nice about this is that while {ggtext} already supports the html tag (which formats text as superscript), it’s not as good as the ordinals font feature. Look how the generic solution (top) doesn’t look as aesthetically pleasing in comparison:\r\n\r\n\r\nsups <- \"1st<\/sup> 2nd<\/sup> 3rd<\/sup> 4th<\/sup>\"\r\n\r\nggplot(NULL) +\r\n geom_richtext(\r\n aes(0, 1, label = sups),\r\n size = 25, family = \"Alegreya-lining\",\r\n fill = NA, label.color = NA\r\n ) +\r\n geom_text(\r\n aes(0, 0, label = \"1st 2nd 3rd 4th\"),\r\n size = 25, family = \"Alegreya-lnum_ordn\"\r\n ) +\r\n scale_y_continuous(expand = expansion(add = 0.5))\r\n\r\n\r\n\r\n\r\nIn my opinion, you should always err towards using the supported font features because they are designed with the particular aesthetics of the font in mind.21 Hopefully this example has convinced you!\r\nUsecases\r\nA mash-up\r\nHere’s a made up plot that mashes up everything we went over so far:\r\n\r\n\r\n\r\n\r\nPlot Code\r\n\r\n\r\n# Setting up fonts (repeat from above)\r\njunebug::font_hoist(\"Font Awesome 5 Free\")\r\njunebug::font_hoist(\"Alegreya\")\r\n\r\nsystemfonts::register_variant(\r\n name = \"Alegreya-lining\",\r\n family = \"Alegreya\",\r\n features = systemfonts::font_feature(numbers = \"lining\")\r\n)\r\nsystemfonts::register_variant(\r\n name = \"Alegreya-lnum_ordn\",\r\n family = \"Alegreya\",\r\n features = systemfonts::font_feature(numbers = \"lining\", \"ordn\" = TRUE)\r\n)\r\n\r\n# labelling function for ordinal format\r\nordinal_style <- function(ordn) {\r\n function (x) {\r\n scales::ordinal_format()(as.integer(x)) %>% \r\n stringr::str_replace(\r\n \"([a-z]+)$\",\r\n stringr::str_glue(\"\\\\1<\/span>\")\r\n )\r\n }\r\n}\r\n\r\n# data\r\nset.seed(2021)\r\nordinal_data <- tibble(\r\n Quarter = as.factor(1:4),\r\n Earnings = c(9, 7, 6, 3) * 1e6\r\n) %>% \r\n arrange(desc(Earnings)) %>% \r\n mutate(\r\n Mood = c(\"smile-beam\", \"meh-blank\", \"meh\", \"dizzy\"),\r\n color = c(\"forestgreen\", \"goldenrod\", \"goldenrod\", \"firebrick\")\r\n )\r\n\r\n# plot\r\nggplot(ordinal_data, aes(Quarter, Earnings)) +\r\n geom_text(\r\n aes(label = Mood, color = color),\r\n size = 18, family = \"Font Awesome 5 Free Solid\"\r\n ) +\r\n scale_color_identity() +\r\n scale_y_continuous(\r\n name = NULL,\r\n labels = scales::label_dollar(),\r\n expand = expansion(0.3)\r\n ) +\r\n scale_x_discrete(\r\n labels = ordinal_style(\"Alegreya-lnum_ordn\")\r\n ) +\r\n labs(title = \"Quarterly Earnings\") +\r\n theme_classic() +\r\n theme(\r\n text = element_text(\r\n size = 14,\r\n family = \"Alegreya\"\r\n ),\r\n axis.text.x = ggtext::element_markdown(\r\n size = 18,\r\n color = \"black\",\r\n family = \"Alegreya-lining\"\r\n ),\r\n axis.text.y = element_text(\r\n size= 14,\r\n color = \"black\",\r\n family = \"Alegreya-lining\"\r\n ),\r\n axis.ticks.x = element_blank(),\r\n axis.title.x = element_text(\r\n size = 18,\r\n family = \"Alegreya Medium\"\r\n ),\r\n plot.title = element_text(\r\n size = 24,\r\n family = \"Alegreya Black\",\r\n margin = margin(b = 5, unit = \"mm\")\r\n )\r\n )\r\n\r\n\r\n\r\nIcon fonts\r\nIf this blog post was your first time encountering icon fonts in R, you probably have a lot of questions right now about using them in data visualizations. You can check out my lightning talk on icon fonts that I gave at RLadies Philly for a quick overview as well as some tips & tricks!\r\n\r\n\r\n\r\n\r\n\r\n\r\nSome extra stuff not mentioned in the talk:\r\n{ragg} supports the rendering of colored fonts like emojis, which also means that it can render colored icon fonts.22 Icons don’t often come in colors, but one example is Google’s Material Icons font (Apache 2.0 license), which has a Two Tone style where icons have a grey fill in addition to a black stroke:23\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"real_estate_agent\"), size = 80,\r\n family = \"Material Icons Two Tone\"\r\n ) +\r\n theme_classic()\r\n \r\n\r\n\r\n\r\nAll fonts based on SVG (pretty much the case for all icon fonts) should work with {ragg} as long as you can get it installed on your local machine. For example, the Bootstrap Icons font (MIT license) only come in .woff and .woff2 formats for web use, but it’s fundamentally just a collection of SVGs, so it can be installed on your local machine once you convert it to .ttf. Then it should just work right out of the box.\r\n\r\n\r\nggplot(NULL, aes(0, 0)) +\r\n geom_text(\r\n aes(label = \"bootstrap-fill\"), color = \"purple\",\r\n size = 80, family = \"bootstrap-icons\"\r\n )\r\n \r\n\r\n\r\n\r\nIf you’re design oriented, you can also make your own icon font for use in R. In Inkscape, you can do this in File > New From Template > Typography Canvas (here’s a guide). Once you save your SVG font, you can convert it to .ttf and follow the same installation process, and then it should be available in R if you render with {ragg}.\r\n\r\n\r\n\r\nFigure 6: Making a font in Inkscape\r\n\r\n\r\n\r\nFor example, here’s my super quick attempt (took me exactly 1 minute) at a one-glyph font that just contains my signature (and you could imagine a usecase where you put this in a corner of your data viz to sign your work):\r\n\r\n\r\nggplot(NULL) +\r\n geom_text(\r\n aes(0, 1, label = \"a\"),\r\n size = 90, family = \"SVGFont 1\"\r\n ) +\r\n geom_text(\r\n aes(0, 0, label = \"a\"),\r\n color = \"red\", angle = 15,\r\n size = 90, family = \"SVGFont 1\"\r\n ) +\r\n scale_y_continuous(expand = expansion(add = c(.5, 1)))\r\n \r\n\r\n\r\n\r\nMore by others\r\nAn extremely detailed step-by-step video walkthrough of using custom fonts in R by @dgkeyes.\r\nThe {hrbragg} package by @hrbrmstr for more utility functions for registering font variants and typography-centered ggplot2 themes.\r\nThe text formatting chapter of Practical Typography by Matthew Butterick for a general guideline on using different font features.\r\nEverything from Thomas Lin Pedersen, the main person responsible for these developments.\r\nMany #TidyTuesday submissions.\r\nOfficial RStudio blog posts:\r\nModern Text Features in R\r\nUpdates to ragg and systemfonts\r\nsvglite 2.0.0\r\nSession info\r\n\r\nSession Info\r\n\r\n R version 4.1.0 (2021-05-18)\r\n Platform: x86_64-w64-mingw32/x64 (64-bit)\r\n Running under: Windows 10 x64 (build 19042)\r\n \r\n Matrix products: default\r\n \r\n locale:\r\n [1] LC_COLLATE=English_United States.1252 \r\n [2] LC_CTYPE=English_United States.1252 \r\n [3] LC_MONETARY=English_United States.1252\r\n [4] LC_NUMERIC=C \r\n [5] LC_TIME=English_United States.1252 \r\n \r\n attached base packages:\r\n [1] stats graphics grDevices utils datasets methods base \r\n \r\n other attached packages:\r\n [1] ggtext_0.1.1 textshaping_0.3.4 stringr_1.4.0 dplyr_1.0.7 \r\n [5] systemfonts_1.0.2 ggplot2_3.3.5 knitr_1.33 \r\n \r\n loaded via a namespace (and not attached):\r\n [1] tidyselect_1.1.1 xfun_0.22 bslib_0.2.5.1 purrr_0.3.4 \r\n [5] colorspace_2.0-2 vctrs_0.3.8 generics_0.1.0 htmltools_0.5.1.1 \r\n [9] yaml_2.2.1 utf8_1.1.4 rlang_0.4.11 gridtext_0.1.4 \r\n [13] jquerylib_0.1.3 pillar_1.6.1 glue_1.4.2 withr_2.4.2 \r\n [17] DBI_1.1.1 fortunes_1.5-4 lifecycle_1.0.0 munsell_0.5.0 \r\n [21] junebug_0.0.0.9000 gtable_0.3.0 ragg_1.1.3 evaluate_0.14 \r\n [25] labeling_0.4.2 markdown_1.1 fansi_0.4.2 highr_0.8 \r\n [29] Rcpp_1.0.6 scales_1.1.1 jsonlite_1.7.2 farver_2.1.0 \r\n [33] distill_1.2 png_0.1-7 digest_0.6.27 stringi_1.6.2 \r\n [37] grid_4.1.0 cli_3.0.1 tools_4.1.0 magrittr_2.0.1 \r\n [41] sass_0.4.0 tibble_3.1.2 crayon_1.4.1 pkgconfig_2.0.3 \r\n [45] downlit_0.2.1 ellipsis_0.3.2 xml2_1.3.2 data.table_1.14.0 \r\n [49] assertthat_0.2.1 rmarkdown_2.8 rstudioapi_0.13 R6_2.5.0 \r\n [53] compiler_4.1.0\r\n\r\n\r\nAnd I can also personally attest that I used to use them until {ragg} was developed, and I never loaded these packages since. But this isn’t a value judgment - if these packages continue to work for you, then great! But do know that there are some known issues with reliability (though to be fair, {extrafont} and {showtext} were one of the first attempts at solving the font rendering issue in R and they’ve actually done a great job over the years!).↩︎\r\nIn fact, text rendering as a whole is an incredibly complicated task. Check out Text Rendering Hates You for a fun and informative read.↩︎\r\nI’m focusing on outputing to bitmap (e.g., .png, .jpeg, .tiff). For other formats like SVG (which I often default to for online material), you can use svglite - read more on the package website.↩︎\r\nCheck out the discussion on this issue and this commit. There’s also been some talk of making AGG the default renderer, though I don’t know if that’s been settled.↩︎\r\nThese are used to calculate DPI (dots per inch). Resolution is in pixels, so res=150 and units=\"inch\" is the same as dpi=150. {ragg} devices don’t have a dpi argument like the default device, so you have to specify both resolution and units.↩︎\r\nin Windows 10, for example, you have to drag and drop fonts onto the “Fonts” section of Settings↩︎\r\nVariable fonts are hit-or-miss because while {ragg} and {systemfonts} do support some variable font features (see the section on Advanced font features), “variable” can mean many different things, some of which are not supported (e.g., variable width). If you install a variable font, it might render with {ragg} but you’re unlikely to be able to tweak its parameters (like change the weight, for example).↩︎\r\nIn my experience, though, static fonts tend to be .ttf and variable fonts tend to be .otf.↩︎\r\n“You can use them freely in your products & projects - print or digital, commercial or otherwise. However, you can’t sell the fonts on their own.”↩︎\r\nAgain, YMMV, but myself and a couple other folks I’ve talked to share this.↩︎\r\nTechnically, it defaults to fontface = \"plain\" which is the same thing, but {systemfonts} and (also probably your OS) calls it the “Regular” style↩︎\r\nIn case you’re wondering, it still errors with “solid”, no caps.↩︎\r\noptions(error = recover) is your friend! And remember to set options(error = NULL) back once you’re done!↩︎\r\nYou might wonder: what’s the {grid} package doing here? Well, {grid} is kinda the “engine” for {ggplot2} that handles the actual “drawing to the canvas”, which is why it’s relevant here. For example, geom_text() returns a Graphical object (“Grob”), specifically grid::textGrob(), that inherits arguments like family and fontface (which are in turn passed into grid::gpar(), where gpar stands for graphical parameters).↩︎\r\nThe same font file also registered as the Bold, Italic, and Bold Italic styles of the family as well, which is what happens by default if you only supply the plain argument to register_font().↩︎\r\nBorrowing terminology from tidyr::hoist(), the under-appreciated beast of list-column workflows↩︎\r\nRegular as “plain”, Bold as “bold”, Italic as “italic”, and Bold Italic as “bold.italic”.↩︎\r\nAlso check out the related “pnum” (proportional numbers) and “tnum” (tabular numbers) features.↩︎\r\ncheck the help page ?systemfonts::font_feature for details.↩︎\r\nAnother solution would be to use the small-cap variant (the “smcp” feature) for “une”.↩︎\r\nBut this also means that not all fonts support “ordn”, while is always available.↩︎\r\nBut not all colored fonts, in my experience.↩︎\r\nThe colors are fixed though - they come colored in black and filled in grey.↩︎\r\n", + "preview": "posts/2021-06-24-setting-up-and-debugging-custom-fonts/preview.png", + "last_modified": "2021-07-29T12:44:56-04:00", + "input_file": {}, + "preview_width": 709, + "preview_height": 612 + }, + { + "path": "posts/2021-01-17-random-sampling-a-table-animation/", + "title": "Random Sampling: A table animation", + "description": "Plus a convenient way of rendering LaTeX expressions as images", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2021-01-17", + "categories": [ + "data visualization", + "data wrangling" + ], + "contents": "\r\n\r\nContents\r\nStatic\r\nAn aside on LaTeX equations\r\n\r\nAnimated\r\nFinal Product\r\n\r\n\r\n\r\n\r\nd-article table th {\r\n font-size: 12px;\r\n}\r\nd-article table td {\r\n font-size: 12px;\r\n}\r\n\r\nIn my last blogpost, I demonstrated a couple use cases for the higher-order functionals reduce() and accumulate() from the {purrr} package. In one example, I made an animated {kableExtra} table by accumulate()-ing over multiple calls to column_spec() that set a background color for a column.\r\nAnimated tables are virtually non-existent in the wild, and probably for a good reason. but I wanted to extend upon my previous table animation and create something that’s maybe a bit more on the “informative” side.\r\nTo that end, here’s an animate table that simulates sampling from a bivariate normal distribution.\r\nStatic\r\nLet’s first start by generating 100,000 data points:\r\n\r\n\r\nset.seed(2021)\r\n\r\nlibrary(dplyr)\r\n\r\nsamples_data <- MASS::mvrnorm(1e5, c(0, 0), matrix(c(1, .7, .7, 1), ncol = 2)) %>% \r\n as_tibble(.name_repair = ~c(\"x\", \"y\")) %>% \r\n mutate(across(everything(), ~ as.character(.x - .x %% 0.2)))\r\n\r\nsamples_data\r\n\r\n\r\n # A tibble: 100,000 x 2\r\n x y \r\n \r\n 1 0 -0.4 \r\n 2 0.2 0.6 \r\n 3 0.4 0.2 \r\n 4 0.6 -0.2 \r\n 5 0.6 0.8 \r\n 6 -1.8 -2 \r\n 7 0.8 -0.6 \r\n 8 1.2 0.4 \r\n 9 0.4 -0.4 \r\n 10 1.4 1.6 \r\n # ... with 99,990 more rows\r\n\r\nLet’s see how this looks when we turn this into a “matrix”1. To place continuous values into discrete cells in the table, I’m also binning both variables by 0.2:\r\n\r\n\r\nsamples_data_spread <- samples_data %>% \r\n count(x, y) %>% \r\n right_join(\r\n tidyr::crossing(\r\n x = as.character(seq(-3, 3, 0.2)),\r\n y = as.character(seq(-3, 3, 0.2))\r\n ),\r\n by = c(\"x\", \"y\")\r\n ) %>% \r\n tidyr::pivot_wider(names_from = y, values_from = n) %>% \r\n arrange(-as.numeric(x)) %>% \r\n select(c(\"x\", as.character(seq(-3, 3, 0.2)))) %>% \r\n rename(\" \" = x)\r\n\r\nsamples_data_spread\r\n\r\n\r\n # A tibble: 31 x 32\r\n ` ` `-3` `-2.8` `-2.6` `-2.4` `-2.2` `-2` `-1.8` `-1.6` `-1.4` `-1.2`\r\n \r\n 1 3 NA NA NA NA NA NA NA NA NA NA\r\n 2 2.8 NA NA NA NA NA NA NA NA NA NA\r\n 3 2.6 NA NA NA NA NA NA NA NA NA NA\r\n 4 2.4 NA NA NA NA NA NA NA NA NA NA\r\n 5 2.2 NA NA NA NA NA NA NA NA NA NA\r\n 6 2 NA NA NA NA NA NA NA NA NA NA\r\n 7 1.8 NA NA NA NA NA NA NA NA NA NA\r\n 8 1.6 NA NA NA NA NA NA NA 1 1 4\r\n 9 1.4 NA NA NA NA NA NA 1 NA 1 4\r\n 10 1.2 NA NA NA NA NA NA NA 3 2 7\r\n # ... with 21 more rows, and 21 more variables: `-1` , `-0.8` ,\r\n # `-0.6` , `-0.4` , `-0.2` , `0` , `0.2` ,\r\n # `0.4` , `0.6` , `0.8` , `1` , `1.2` , `1.4` ,\r\n # `1.6` , `1.8` , `2` , `2.2` , `2.4` , `2.6` ,\r\n # `2.8` , `3` \r\n\r\nNow we can turn this into a table and fill the cells according to the counts using reduce():\r\n\r\n\r\nlibrary(kableExtra)\r\n\r\nsamples_data_table <- samples_data_spread %>% \r\n kable() %>% \r\n kable_classic() %>% \r\n purrr::reduce(2L:length(samples_data_spread), ~ {\r\n column_spec(\r\n kable_input = .x,\r\n column = .y,\r\n background = spec_color(\r\n samples_data_spread[[.y]],\r\n scale_from = c(1, max(as.numeric(as.matrix(samples_data_spread)), na.rm = TRUE)),\r\n na_color = \"white\",\r\n option = \"plasma\"\r\n ),\r\n color = \"white\"\r\n )},\r\n .init = .\r\n )\r\n\r\nsamples_data_table\r\n\r\n\r\n\r\n\r\n\r\n-3\r\n\r\n\r\n-2.8\r\n\r\n\r\n-2.6\r\n\r\n\r\n-2.4\r\n\r\n\r\n-2.2\r\n\r\n\r\n-2\r\n\r\n\r\n-1.8\r\n\r\n\r\n-1.6\r\n\r\n\r\n-1.4\r\n\r\n\r\n-1.2\r\n\r\n\r\n-1\r\n\r\n\r\n-0.8\r\n\r\n\r\n-0.6\r\n\r\n\r\n-0.4\r\n\r\n\r\n-0.2\r\n\r\n\r\n0\r\n\r\n\r\n0.2\r\n\r\n\r\n0.4\r\n\r\n\r\n0.6\r\n\r\n\r\n0.8\r\n\r\n\r\n1\r\n\r\n\r\n1.2\r\n\r\n\r\n1.4\r\n\r\n\r\n1.6\r\n\r\n\r\n1.8\r\n\r\n\r\n2\r\n\r\n\r\n2.2\r\n\r\n\r\n2.4\r\n\r\n\r\n2.6\r\n\r\n\r\n2.8\r\n\r\n\r\n3\r\n\r\n\r\n3\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n8\r\n\r\n\r\n2\r\n\r\n\r\n7\r\n\r\n\r\n7\r\n\r\n\r\n8\r\n\r\n\r\n4\r\n\r\n\r\n6\r\n\r\n\r\n6\r\n\r\n\r\n2\r\n\r\n\r\n1\r\n\r\n\r\n2.8\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\n3\r\n\r\n\r\n6\r\n\r\n\r\n6\r\n\r\n\r\n20\r\n\r\n\r\n14\r\n\r\n\r\n20\r\n\r\n\r\n15\r\n\r\n\r\n8\r\n\r\n\r\n18\r\n\r\n\r\n6\r\n\r\n\r\n10\r\n\r\n\r\n7\r\n\r\n\r\n3\r\n\r\n\r\n2.6\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n7\r\n\r\n\r\n11\r\n\r\n\r\n21\r\n\r\n\r\n26\r\n\r\n\r\n17\r\n\r\n\r\n26\r\n\r\n\r\n29\r\n\r\n\r\n28\r\n\r\n\r\n21\r\n\r\n\r\n17\r\n\r\n\r\n10\r\n\r\n\r\n3\r\n\r\n\r\n8\r\n\r\n\r\n2.4\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n7\r\n\r\n\r\n11\r\n\r\n\r\n17\r\n\r\n\r\n20\r\n\r\n\r\n32\r\n\r\n\r\n33\r\n\r\n\r\n43\r\n\r\n\r\n52\r\n\r\n\r\n43\r\n\r\n\r\n37\r\n\r\n\r\n23\r\n\r\n\r\n23\r\n\r\n\r\n17\r\n\r\n\r\n9\r\n\r\n\r\n7\r\n\r\n\r\n2.2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n3\r\n\r\n\r\n7\r\n\r\n\r\n6\r\n\r\n\r\n12\r\n\r\n\r\n20\r\n\r\n\r\n18\r\n\r\n\r\n46\r\n\r\n\r\n51\r\n\r\n\r\n59\r\n\r\n\r\n66\r\n\r\n\r\n58\r\n\r\n\r\n73\r\n\r\n\r\n53\r\n\r\n\r\n41\r\n\r\n\r\n21\r\n\r\n\r\n20\r\n\r\n\r\n16\r\n\r\n\r\n8\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\n12\r\n\r\n\r\n17\r\n\r\n\r\n20\r\n\r\n\r\n35\r\n\r\n\r\n53\r\n\r\n\r\n83\r\n\r\n\r\n103\r\n\r\n\r\n93\r\n\r\n\r\n117\r\n\r\n\r\n106\r\n\r\n\r\n111\r\n\r\n\r\n74\r\n\r\n\r\n52\r\n\r\n\r\n42\r\n\r\n\r\n27\r\n\r\n\r\n17\r\n\r\n\r\n5\r\n\r\n\r\n1.8\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n8\r\n\r\n\r\n10\r\n\r\n\r\n14\r\n\r\n\r\n40\r\n\r\n\r\n50\r\n\r\n\r\n81\r\n\r\n\r\n108\r\n\r\n\r\n128\r\n\r\n\r\n132\r\n\r\n\r\n149\r\n\r\n\r\n143\r\n\r\n\r\n146\r\n\r\n\r\n103\r\n\r\n\r\n89\r\n\r\n\r\n57\r\n\r\n\r\n39\r\n\r\n\r\n19\r\n\r\n\r\n23\r\n\r\n\r\n7\r\n\r\n\r\n1.6\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n6\r\n\r\n\r\n6\r\n\r\n\r\n14\r\n\r\n\r\n19\r\n\r\n\r\n39\r\n\r\n\r\n67\r\n\r\n\r\n99\r\n\r\n\r\n136\r\n\r\n\r\n148\r\n\r\n\r\n183\r\n\r\n\r\n197\r\n\r\n\r\n214\r\n\r\n\r\n185\r\n\r\n\r\n170\r\n\r\n\r\n109\r\n\r\n\r\n81\r\n\r\n\r\n60\r\n\r\n\r\n40\r\n\r\n\r\n24\r\n\r\n\r\n11\r\n\r\n\r\n11\r\n\r\n\r\n1.4\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n8\r\n\r\n\r\n17\r\n\r\n\r\n37\r\n\r\n\r\n50\r\n\r\n\r\n74\r\n\r\n\r\n115\r\n\r\n\r\n170\r\n\r\n\r\n225\r\n\r\n\r\n277\r\n\r\n\r\n307\r\n\r\n\r\n323\r\n\r\n\r\n292\r\n\r\n\r\n243\r\n\r\n\r\n186\r\n\r\n\r\n123\r\n\r\n\r\n110\r\n\r\n\r\n61\r\n\r\n\r\n47\r\n\r\n\r\n19\r\n\r\n\r\n7\r\n\r\n\r\n3\r\n\r\n\r\n1.2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\n7\r\n\r\n\r\n22\r\n\r\n\r\n29\r\n\r\n\r\n60\r\n\r\n\r\n88\r\n\r\n\r\n144\r\n\r\n\r\n204\r\n\r\n\r\n273\r\n\r\n\r\n317\r\n\r\n\r\n376\r\n\r\n\r\n381\r\n\r\n\r\n337\r\n\r\n\r\n323\r\n\r\n\r\n262\r\n\r\n\r\n208\r\n\r\n\r\n135\r\n\r\n\r\n92\r\n\r\n\r\n58\r\n\r\n\r\n41\r\n\r\n\r\n17\r\n\r\n\r\n8\r\n\r\n\r\n7\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n5\r\n\r\n\r\n6\r\n\r\n\r\n18\r\n\r\n\r\n26\r\n\r\n\r\n64\r\n\r\n\r\n83\r\n\r\n\r\n160\r\n\r\n\r\n239\r\n\r\n\r\n329\r\n\r\n\r\n375\r\n\r\n\r\n504\r\n\r\n\r\n501\r\n\r\n\r\n474\r\n\r\n\r\n455\r\n\r\n\r\n336\r\n\r\n\r\n315\r\n\r\n\r\n223\r\n\r\n\r\n154\r\n\r\n\r\n94\r\n\r\n\r\n52\r\n\r\n\r\n23\r\n\r\n\r\n11\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\n0.8\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n4\r\n\r\n\r\n8\r\n\r\n\r\n10\r\n\r\n\r\n29\r\n\r\n\r\n68\r\n\r\n\r\n104\r\n\r\n\r\n163\r\n\r\n\r\n269\r\n\r\n\r\n336\r\n\r\n\r\n375\r\n\r\n\r\n517\r\n\r\n\r\n566\r\n\r\n\r\n612\r\n\r\n\r\n572\r\n\r\n\r\n480\r\n\r\n\r\n355\r\n\r\n\r\n256\r\n\r\n\r\n190\r\n\r\n\r\n129\r\n\r\n\r\n58\r\n\r\n\r\n37\r\n\r\n\r\n14\r\n\r\n\r\n14\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\n0.6\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n9\r\n\r\n\r\n20\r\n\r\n\r\n39\r\n\r\n\r\n62\r\n\r\n\r\n104\r\n\r\n\r\n161\r\n\r\n\r\n272\r\n\r\n\r\n373\r\n\r\n\r\n459\r\n\r\n\r\n591\r\n\r\n\r\n674\r\n\r\n\r\n684\r\n\r\n\r\n641\r\n\r\n\r\n587\r\n\r\n\r\n487\r\n\r\n\r\n365\r\n\r\n\r\n251\r\n\r\n\r\n167\r\n\r\n\r\n97\r\n\r\n\r\n56\r\n\r\n\r\n25\r\n\r\n\r\n9\r\n\r\n\r\n5\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\n0.4\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n4\r\n\r\n\r\n27\r\n\r\n\r\n32\r\n\r\n\r\n60\r\n\r\n\r\n101\r\n\r\n\r\n159\r\n\r\n\r\n260\r\n\r\n\r\n413\r\n\r\n\r\n535\r\n\r\n\r\n680\r\n\r\n\r\n794\r\n\r\n\r\n796\r\n\r\n\r\n780\r\n\r\n\r\n704\r\n\r\n\r\n537\r\n\r\n\r\n452\r\n\r\n\r\n345\r\n\r\n\r\n218\r\n\r\n\r\n119\r\n\r\n\r\n69\r\n\r\n\r\n38\r\n\r\n\r\n16\r\n\r\n\r\n8\r\n\r\n\r\n10\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n0.2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\n2\r\n\r\n\r\n9\r\n\r\n\r\n33\r\n\r\n\r\n46\r\n\r\n\r\n91\r\n\r\n\r\n152\r\n\r\n\r\n229\r\n\r\n\r\n388\r\n\r\n\r\n519\r\n\r\n\r\n654\r\n\r\n\r\n777\r\n\r\n\r\n851\r\n\r\n\r\n881\r\n\r\n\r\n712\r\n\r\n\r\n674\r\n\r\n\r\n535\r\n\r\n\r\n389\r\n\r\n\r\n285\r\n\r\n\r\n176\r\n\r\n\r\n102\r\n\r\n\r\n45\r\n\r\n\r\n29\r\n\r\n\r\n14\r\n\r\n\r\n7\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n0\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\n11\r\n\r\n\r\n18\r\n\r\n\r\n51\r\n\r\n\r\n77\r\n\r\n\r\n154\r\n\r\n\r\n210\r\n\r\n\r\n351\r\n\r\n\r\n521\r\n\r\n\r\n645\r\n\r\n\r\n778\r\n\r\n\r\n876\r\n\r\n\r\n866\r\n\r\n\r\n812\r\n\r\n\r\n685\r\n\r\n\r\n593\r\n\r\n\r\n459\r\n\r\n\r\n296\r\n\r\n\r\n190\r\n\r\n\r\n117\r\n\r\n\r\n50\r\n\r\n\r\n39\r\n\r\n\r\n24\r\n\r\n\r\n8\r\n\r\n\r\n2\r\n\r\n\r\n2\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\n-0.2\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n1\r\n\r\n\r\n6\r\n\r\n\r\n15\r\n\r\n\r\n36\r\n\r\n\r\n59\r\n\r\n\r\n112\r\n\r\n\r\n196\r\n\r\n\r\n286\r\n\r\n\r\n410\r\n\r\n\r\n620\r\n\r\n\r\n747\r\n\r\n\r\n856\r\n\r\n\r\n854\r\n\r\n\r\n836\r\n\r\n\r\n721\r\n\r\n\r\n683\r\n\r\n\r\n493\r\n\r\n\r\n344\r\n\r\n\r\n215\r\n\r\n\r\n162\r\n\r\n\r\n70\r\n\r\n\r\n50\r\n\r\n\r\n21\r\n\r\n\r\n6\r\n\r\n\r\n5\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-0.4\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\n12\r\n\r\n\r\n24\r\n\r\n\r\n60\r\n\r\n\r\n85\r\n\r\n\r\n168\r\n\r\n\r\n256\r\n\r\n\r\n373\r\n\r\n\r\n551\r\n\r\n\r\n689\r\n\r\n\r\n785\r\n\r\n\r\n842\r\n\r\n\r\n776\r\n\r\n\r\n773\r\n\r\n\r\n683\r\n\r\n\r\n504\r\n\r\n\r\n395\r\n\r\n\r\n233\r\n\r\n\r\n154\r\n\r\n\r\n94\r\n\r\n\r\n43\r\n\r\n\r\n35\r\n\r\n\r\n7\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-0.6\r\n\r\n\r\nNA\r\n\r\n\r\n4\r\n\r\n\r\n13\r\n\r\n\r\n16\r\n\r\n\r\n30\r\n\r\n\r\n62\r\n\r\n\r\n119\r\n\r\n\r\n219\r\n\r\n\r\n331\r\n\r\n\r\n447\r\n\r\n\r\n573\r\n\r\n\r\n714\r\n\r\n\r\n736\r\n\r\n\r\n787\r\n\r\n\r\n725\r\n\r\n\r\n658\r\n\r\n\r\n524\r\n\r\n\r\n389\r\n\r\n\r\n255\r\n\r\n\r\n219\r\n\r\n\r\n108\r\n\r\n\r\n66\r\n\r\n\r\n37\r\n\r\n\r\n5\r\n\r\n\r\n8\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-0.8\r\n\r\n\r\n3\r\n\r\n\r\n8\r\n\r\n\r\n13\r\n\r\n\r\n40\r\n\r\n\r\n59\r\n\r\n\r\n81\r\n\r\n\r\n181\r\n\r\n\r\n263\r\n\r\n\r\n330\r\n\r\n\r\n469\r\n\r\n\r\n600\r\n\r\n\r\n661\r\n\r\n\r\n681\r\n\r\n\r\n652\r\n\r\n\r\n639\r\n\r\n\r\n484\r\n\r\n\r\n368\r\n\r\n\r\n274\r\n\r\n\r\n160\r\n\r\n\r\n123\r\n\r\n\r\n48\r\n\r\n\r\n26\r\n\r\n\r\n13\r\n\r\n\r\n10\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-1\r\n\r\n\r\n6\r\n\r\n\r\n8\r\n\r\n\r\n21\r\n\r\n\r\n34\r\n\r\n\r\n80\r\n\r\n\r\n133\r\n\r\n\r\n195\r\n\r\n\r\n293\r\n\r\n\r\n386\r\n\r\n\r\n457\r\n\r\n\r\n556\r\n\r\n\r\n626\r\n\r\n\r\n574\r\n\r\n\r\n526\r\n\r\n\r\n461\r\n\r\n\r\n363\r\n\r\n\r\n246\r\n\r\n\r\n190\r\n\r\n\r\n105\r\n\r\n\r\n56\r\n\r\n\r\n26\r\n\r\n\r\n16\r\n\r\n\r\n6\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-1.2\r\n\r\n\r\n10\r\n\r\n\r\n8\r\n\r\n\r\n21\r\n\r\n\r\n45\r\n\r\n\r\n77\r\n\r\n\r\n146\r\n\r\n\r\n198\r\n\r\n\r\n266\r\n\r\n\r\n360\r\n\r\n\r\n436\r\n\r\n\r\n469\r\n\r\n\r\n480\r\n\r\n\r\n457\r\n\r\n\r\n393\r\n\r\n\r\n344\r\n\r\n\r\n242\r\n\r\n\r\n169\r\n\r\n\r\n104\r\n\r\n\r\n79\r\n\r\n\r\n33\r\n\r\n\r\n23\r\n\r\n\r\n9\r\n\r\n\r\n2\r\n\r\n\r\n3\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-1.4\r\n\r\n\r\n6\r\n\r\n\r\n13\r\n\r\n\r\n31\r\n\r\n\r\n62\r\n\r\n\r\n96\r\n\r\n\r\n163\r\n\r\n\r\n200\r\n\r\n\r\n299\r\n\r\n\r\n337\r\n\r\n\r\n360\r\n\r\n\r\n364\r\n\r\n\r\n364\r\n\r\n\r\n319\r\n\r\n\r\n239\r\n\r\n\r\n190\r\n\r\n\r\n129\r\n\r\n\r\n84\r\n\r\n\r\n50\r\n\r\n\r\n33\r\n\r\n\r\n17\r\n\r\n\r\n11\r\n\r\n\r\n7\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-1.6\r\n\r\n\r\n18\r\n\r\n\r\n25\r\n\r\n\r\n39\r\n\r\n\r\n61\r\n\r\n\r\n110\r\n\r\n\r\n138\r\n\r\n\r\n184\r\n\r\n\r\n235\r\n\r\n\r\n281\r\n\r\n\r\n278\r\n\r\n\r\n294\r\n\r\n\r\n246\r\n\r\n\r\n211\r\n\r\n\r\n176\r\n\r\n\r\n148\r\n\r\n\r\n92\r\n\r\n\r\n40\r\n\r\n\r\n23\r\n\r\n\r\n17\r\n\r\n\r\n8\r\n\r\n\r\n5\r\n\r\n\r\n3\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-1.8\r\n\r\n\r\n11\r\n\r\n\r\n19\r\n\r\n\r\n33\r\n\r\n\r\n52\r\n\r\n\r\n90\r\n\r\n\r\n139\r\n\r\n\r\n165\r\n\r\n\r\n185\r\n\r\n\r\n225\r\n\r\n\r\n192\r\n\r\n\r\n206\r\n\r\n\r\n157\r\n\r\n\r\n125\r\n\r\n\r\n100\r\n\r\n\r\n62\r\n\r\n\r\n40\r\n\r\n\r\n28\r\n\r\n\r\n11\r\n\r\n\r\n10\r\n\r\n\r\n2\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-2\r\n\r\n\r\n11\r\n\r\n\r\n29\r\n\r\n\r\n34\r\n\r\n\r\n50\r\n\r\n\r\n78\r\n\r\n\r\n102\r\n\r\n\r\n139\r\n\r\n\r\n141\r\n\r\n\r\n144\r\n\r\n\r\n149\r\n\r\n\r\n110\r\n\r\n\r\n104\r\n\r\n\r\n76\r\n\r\n\r\n49\r\n\r\n\r\n41\r\n\r\n\r\n19\r\n\r\n\r\n19\r\n\r\n\r\n5\r\n\r\n\r\n4\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-2.2\r\n\r\n\r\n11\r\n\r\n\r\n23\r\n\r\n\r\n38\r\n\r\n\r\n48\r\n\r\n\r\n76\r\n\r\n\r\n76\r\n\r\n\r\n99\r\n\r\n\r\n105\r\n\r\n\r\n88\r\n\r\n\r\n81\r\n\r\n\r\n81\r\n\r\n\r\n72\r\n\r\n\r\n36\r\n\r\n\r\n20\r\n\r\n\r\n25\r\n\r\n\r\n9\r\n\r\n\r\n6\r\n\r\n\r\n4\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-2.4\r\n\r\n\r\n12\r\n\r\n\r\n21\r\n\r\n\r\n24\r\n\r\n\r\n44\r\n\r\n\r\n56\r\n\r\n\r\n53\r\n\r\n\r\n51\r\n\r\n\r\n69\r\n\r\n\r\n66\r\n\r\n\r\n54\r\n\r\n\r\n46\r\n\r\n\r\n24\r\n\r\n\r\n21\r\n\r\n\r\n9\r\n\r\n\r\n5\r\n\r\n\r\n7\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-2.6\r\n\r\n\r\n12\r\n\r\n\r\n15\r\n\r\n\r\n20\r\n\r\n\r\n34\r\n\r\n\r\n32\r\n\r\n\r\n30\r\n\r\n\r\n40\r\n\r\n\r\n34\r\n\r\n\r\n36\r\n\r\n\r\n28\r\n\r\n\r\n21\r\n\r\n\r\n15\r\n\r\n\r\n8\r\n\r\n\r\n4\r\n\r\n\r\n2\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-2.8\r\n\r\n\r\n5\r\n\r\n\r\n17\r\n\r\n\r\n28\r\n\r\n\r\n27\r\n\r\n\r\n19\r\n\r\n\r\n14\r\n\r\n\r\n20\r\n\r\n\r\n26\r\n\r\n\r\n15\r\n\r\n\r\n10\r\n\r\n\r\n10\r\n\r\n\r\n4\r\n\r\n\r\n2\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\n-3\r\n\r\n\r\n6\r\n\r\n\r\n10\r\n\r\n\r\n3\r\n\r\n\r\n11\r\n\r\n\r\n21\r\n\r\n\r\n11\r\n\r\n\r\n13\r\n\r\n\r\n6\r\n\r\n\r\n10\r\n\r\n\r\n8\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n3\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nNA\r\n\r\n\r\nAn aside on LaTeX equations\r\nAs an aside, let’s say we also want to annotate this table with the true distribution where this sample came from. As specified in our call to MASS::mvrnorm() used to make samples_data, the distribution is one where both variables have a mean of 0 and a standard deviation of 1, plus a correlation of 0.7:\r\n\\[\\begin{bmatrix} X \\\\ Y \\end{bmatrix}\\ \\sim\\ N(\\begin{bmatrix} 0 \\\\ 0 \\end{bmatrix},\\begin{bmatrix}1 & 0.7 \\\\ 0.7 & 1 \\end{bmatrix})\\]\r\nWhere the LaTeX code for the above formula is:\r\n\r\n \\begin{bmatrix} X \\\\ Y \\end{bmatrix}\\ \\sim\\\r\n N(\\begin{bmatrix} 0 \\\\ 0 \\end{bmatrix},\r\n \\begin{bmatrix}1 & 0.7 \\\\ 0.7 & 1 \\end{bmatrix})\r\n\r\nMany different solutions already exist to LaTeX math annotations. The most common is probably Non-Standard Evaluation (NSE) methods using parse(), expression(), bquote() etc. There are bulkier solutions like the {latex2exp} package that plots plotmath expressions, though it hasn’t been updated since 2015 and I personally had difficulty getting it to work.\r\nOne solution I’ve never heard of/considered before is querying a web LaTeX editor that has an API. The Online LaTeX Equation Editor by CodeCogs is the perfect example of this. A simple link that contains the LaTeX code in a URL-compatible encoding renders the resulting expression as an image!\r\nI wrote a function latex_query (not thoroughly tested) in my personal package that takes LaTeX code and generates a CodeCogs URL containing the rendered expression2\r\n\r\n\r\n# NOTE the string literal syntax using r\"(...)\" is only available in R 4.0.0 and up\r\nlatex_url <- junebug::latex_query(\r\n formula = r\"(\\begin{bmatrix} X \\\\ Y \\end{bmatrix}\\ \\sim\\\r\n N(\\begin{bmatrix} 0 \\\\ 0 \\end{bmatrix},\r\n \\begin{bmatrix}1 & 0.7 \\\\ 0.7 & 1 \\end{bmatrix}))\",\r\n dpi = 150\r\n)\r\n\r\nknitr::include_graphics(latex_url)\r\n\r\n\r\n\r\n\r\nThe variable latex_url is this really long URL which, as we see above, points to a rendered image of the LaTeX expression we fed it!\r\nAnnotating our table, then, is pretty straightforward. We save it as an image, read in the LaTeX equation as an image, then combine!\r\n\r\n\r\nsave_kable(samples_data_table, \"img/samples_data_table.png\")\r\n\r\nlibrary(magick)\r\n\r\nimage_composite(\r\n image_read(\"img/samples_data_table.png\"),\r\n image_read(latex_url),\r\n offset = \"+50+50\"\r\n)\r\n\r\n\r\n\r\n\r\n\r\n\r\nAnimated\r\nFor an animated version, we add a step where we split the data at every 10,000 additional samples before binning the observations into cells. We then draw a table at each point of the accumulation using {kableExtra} with the help of map() and reduce() (plus some more kable styling).\r\n\r\n\r\nsamples_tables <- purrr::map(1L:10L, ~{\r\n samples_slice <- samples_data %>% \r\n slice(1L:(.x * 1e4)) %>% \r\n count(x, y) %>% \r\n right_join(\r\n tidyr::crossing(\r\n x = as.character(seq(-3, 3, 0.2)),\r\n y = as.character(seq(-3, 3, 0.2))\r\n ),\r\n by = c(\"x\", \"y\")\r\n ) %>% \r\n tidyr::pivot_wider(names_from = y, values_from = n) %>% \r\n arrange(-as.numeric(x)) %>% \r\n select(c(\"x\", as.character(seq(-3, 3, 0.2)))) %>% \r\n rename(\" \" = x)\r\n\r\n \r\n samples_slice %>%\r\n kable() %>% \r\n kable_classic() %>% \r\n purrr::reduce(\r\n 2L:length(samples_slice),\r\n ~ {\r\n .x %>% \r\n column_spec(\r\n column = .y,\r\n width_min = \"35px\",\r\n background = spec_color(\r\n samples_slice[[.y]],\r\n scale_from = c(1, max(as.numeric(as.matrix(samples_slice)), na.rm = TRUE)),\r\n na_color = \"white\",\r\n option = \"plasma\"\r\n ),\r\n color = \"white\"\r\n ) %>% \r\n row_spec(\r\n row = .y - 1L,\r\n hline_after = FALSE,\r\n extra_css = \"border-top:none; padding-top:15px;\"\r\n )\r\n },\r\n .init = .\r\n ) %>% \r\n row_spec(0L, bold = TRUE) %>% \r\n column_spec(1L, bold = TRUE, border_right = TRUE) %>% \r\n kable_styling(\r\n full_width = F,\r\n font_size = 10,\r\n html_font = \"IBM Plex Mono\",\r\n )\r\n})\r\n\r\n\r\n\r\nThe result, samples_tables is a list of tables. We can walk() over that list with save_kable() to write them as images and then read them back in with {magick}:\r\n\r\n\r\npurrr::iwalk(samples_tables, ~ save_kable(.x, file = glue::glue(\"tbl_imgs/tbl{.y}.png\")))\r\n\r\ntable_imgs <- image_read(paste0(\"tbl_imgs/tbl\", 1:10, \".png\"))\r\n\r\n\r\n\r\nNow we can add our LaTeX expression from the previous section as an annotation to these table images using image_composite():\r\n\r\n\r\ntable_imgs_annotated <- table_imgs %>% \r\n image_composite(\r\n image_read(latex_url),\r\n offset = \"+100+80\"\r\n )\r\n\r\n\r\n\r\nFinally, we just patch the table images together into an animation using image_animate() and we have our animated table!\r\n\r\n\r\ntable_imgs_animated <- table_imgs_annotated %>% \r\n image_animate(optimize = TRUE)\r\n\r\n\r\n\r\nFinal Product\r\n\r\n\r\n\r\nYou can also see the difference in the degree of “interpolation” by directly comparing the table at 10 thousand vs 100 thousand samples (the first and last frames):\r\n\r\n\r\n\r\nNeat!\r\n\r\nVisually speaking. It’s still a dataframe object for compatibility with {kableExtra}↩︎\r\nDetails about the API - https://www.codecogs.com/latex/editor-api.php↩︎\r\n", + "preview": "posts/2021-01-17-random-sampling-a-table-animation/table_preview.png", + "last_modified": "2021-01-17T18:31:53-05:00", + "input_file": {}, + "preview_width": 1185, + "preview_height": 1180 + }, + { + "path": "posts/2020-12-13-collapse-repetitive-piping-with-reduce/", + "title": "Collapse repetitive piping with reduce()", + "description": "Featuring accumulate()", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-12-13", + "categories": [ + "data wrangling", + "tutorial" + ], + "contents": "\r\n\r\nContents\r\nIntroduction\r\nHappy pipes\r\nSad (repetitive) pipes\r\nIntroducing purrr::reduce()\r\n\r\nExample 1: {ggplot2}\r\nA reduce() solution\r\nfeat. accumulate()\r\n\r\nExample 2: {kableExtra}\r\nA reduce2() solution\r\nfeat. accumulate2()\r\n\r\nExample 3: {dplyr}\r\nA reduce() solution\r\nfeat. {data.table}\r\n\r\nMisc.\r\n\r\n\r\n\r\n\r\n\r\n\r\ntable.lightable-classic {\r\n margin-bottom: 30px;\r\n}\r\n\r\nIntroduction\r\nHappy pipes\r\nModern day programming with R is all about pipes.1 You start out with some object that undergoes incremental changes as it is passed (piped) into a chain of functions and finally returned as the desired output, like in this simple example. 2\r\n\r\n\r\nset.seed(2021) # Can 2020 be over already?\r\n\r\nsquare <- function(x) x^2\r\ndeviation <- function(x) x - mean(x)\r\n\r\nnums <- runif(100)\r\n\r\nnums %>%\r\n deviation() %>%\r\n square() %>%\r\n mean() %>%\r\n sqrt()\r\n\r\n\r\n [1] 0.3039881\r\n\r\nWhen we pipe (or pass anything through any function, for that matter), we often do one distinct thing at a time, like in the above example.\r\nSo, we rarely have a chain of functions that look like this:\r\n\r\n\r\nlibrary(dplyr)\r\n\r\nmtcars %>% \r\n mutate(kmpg = mpg/1.6) %>% \r\n mutate(disp = round(disp)) %>% \r\n select(-vs) %>% \r\n select(-am) %>% \r\n select(-gear) %>% \r\n select(-carb) %>% \r\n filter(mpg > 15) %>% \r\n filter(cyl == 6) %>% \r\n filter(wt < 3)\r\n\r\n\r\n\r\n… because many functions are vectorized, or designed to handle multiple values by other means, like this:\r\n\r\n\r\npenguins %>% \r\n mutate(kmpg = mpg/1.6, disp = round(disp)) %>% \r\n select(-(vs:carb)) %>% \r\n filter(mpg > 15, cyl == 6, wt < 3)\r\n\r\n\r\n\r\nSad (repetitive) pipes\r\nBut some functions do not handle multiple inputs the way we want it to, or just not at all. Here are some examples of what I’m talking about.\r\nIn {ggplot2}, this doesn’t plot 3 overlapping points with sizes 8, 4, and 2:\r\n\r\n\r\nlibrary(ggplot2)\r\n\r\nggplot(mtcars, aes(hp, mpg)) + \r\n geom_point(size = c(8, 4, 2), alpha = .5)\r\n\r\n\r\n Error: Aesthetics must be either length 1 or the same as the data (32): size\r\n\r\nSo you have to do this:\r\n\r\n\r\nggplot(mtcars, aes(hp, mpg)) + \r\n geom_point(size = 8, alpha = .5) +\r\n geom_point(size = 4, alpha = .5) +\r\n geom_point(size = 2, alpha = .5)\r\n\r\n\r\n\r\n\r\nIn {kableExtra}, this doesn’t color the third column “skyblue”, the fourth column “forestgreen”, and the fifth column “chocolate”:3\r\n\r\n\r\nlibrary(kableExtra)\r\n\r\nmtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% \r\n column_spec(3:5, background = c(\"skyblue\", \"forestgreen\", \"chocolate\"))\r\n\r\n\r\n Warning in ensure_len_html(background, nrows, \"background\"): The number of\r\n provided values in background does not equal to the number of rows.\r\n\r\n\r\n\r\nmpg\r\n\r\n\r\ncyl\r\n\r\n\r\ndisp\r\n\r\n\r\nhp\r\n\r\n\r\ndrat\r\n\r\n\r\nwt\r\n\r\n\r\nqsec\r\n\r\n\r\nvs\r\n\r\n\r\nam\r\n\r\n\r\ngear\r\n\r\n\r\ncarb\r\n\r\n\r\nMazda RX4\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.620\r\n\r\n\r\n16.46\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nMazda RX4 Wag\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.875\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nDatsun 710\r\n\r\n\r\n22.8\r\n\r\n\r\n4\r\n\r\n\r\n108\r\n\r\n\r\n93\r\n\r\n\r\n3.85\r\n\r\n\r\n2.320\r\n\r\n\r\n18.61\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\nHornet 4 Drive\r\n\r\n\r\n21.4\r\n\r\n\r\n6\r\n\r\n\r\n258\r\n\r\n\r\n110\r\n\r\n\r\n3.08\r\n\r\n\r\n3.215\r\n\r\n\r\n19.44\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nHornet Sportabout\r\n\r\n\r\n18.7\r\n\r\n\r\n8\r\n\r\n\r\n360\r\n\r\n\r\n175\r\n\r\n\r\n3.15\r\n\r\n\r\n3.440\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\nValiant\r\n\r\n\r\n18.1\r\n\r\n\r\n6\r\n\r\n\r\n225\r\n\r\n\r\n105\r\n\r\n\r\n2.76\r\n\r\n\r\n3.460\r\n\r\n\r\n20.22\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nSo you have to do this:\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% \r\n column_spec(3, background = \"skyblue\") %>% \r\n column_spec(4, background = \"forestgreen\") %>% \r\n column_spec(5, background = \"chocolate\")\r\n\r\n\r\n\r\n\r\n\r\nmpg\r\n\r\n\r\ncyl\r\n\r\n\r\ndisp\r\n\r\n\r\nhp\r\n\r\n\r\ndrat\r\n\r\n\r\nwt\r\n\r\n\r\nqsec\r\n\r\n\r\nvs\r\n\r\n\r\nam\r\n\r\n\r\ngear\r\n\r\n\r\ncarb\r\n\r\n\r\nMazda RX4\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.620\r\n\r\n\r\n16.46\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nMazda RX4 Wag\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.875\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nDatsun 710\r\n\r\n\r\n22.8\r\n\r\n\r\n4\r\n\r\n\r\n108\r\n\r\n\r\n93\r\n\r\n\r\n3.85\r\n\r\n\r\n2.320\r\n\r\n\r\n18.61\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\nHornet 4 Drive\r\n\r\n\r\n21.4\r\n\r\n\r\n6\r\n\r\n\r\n258\r\n\r\n\r\n110\r\n\r\n\r\n3.08\r\n\r\n\r\n3.215\r\n\r\n\r\n19.44\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nHornet Sportabout\r\n\r\n\r\n18.7\r\n\r\n\r\n8\r\n\r\n\r\n360\r\n\r\n\r\n175\r\n\r\n\r\n3.15\r\n\r\n\r\n3.440\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\nValiant\r\n\r\n\r\n18.1\r\n\r\n\r\n6\r\n\r\n\r\n225\r\n\r\n\r\n105\r\n\r\n\r\n2.76\r\n\r\n\r\n3.460\r\n\r\n\r\n20.22\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nIn {dplyr}, this doesn’t make 3 new columns named “a”, “b”, and “c”, all filled with NA:4\r\n\r\n\r\nnew_cols <- c(\"a\", \"b\", \"c\")\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n mutate(!!new_cols := NA)\r\n\r\n\r\n Error: The LHS of `:=` must be a string or a symbol\r\n\r\nSo you have to do either one of these:5\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n mutate(\r\n !!new_cols[1] := NA,\r\n !!new_cols[2] := NA,\r\n !!new_cols[3] := NA\r\n )\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n mutate(!!new_cols[1] := NA) %>% \r\n mutate(!!new_cols[2] := NA) %>% \r\n mutate(!!new_cols[3] := NA)\r\n\r\n\r\n\r\n\r\n mpg a b c\r\n 1 21.0 NA NA NA\r\n 2 21.0 NA NA NA\r\n 3 22.8 NA NA NA\r\n 4 21.4 NA NA NA\r\n 5 18.7 NA NA NA\r\n 6 18.1 NA NA NA\r\n\r\nSo we’ve got functions being repeated, but in all these cases it looks like we can’t just throw in a vector and expect the function to loop/map over them internally in the specific way that we want it to. And the “correct ways” I provided here are not very satisfying: that’s a lot of copying and pasting!\r\nPersonally, I think it’d be nice to collapse these repetitive calls - but how?\r\nIntroducing purrr::reduce()\r\nThe reduce() function from the {purrr} package is a powerful functional that allows you to abstract away from a sequence of functions that are applied in a fixed direction. You should go give Advanced R Ch. 9.5 a read if you want an in-depth explanation, but here I’m just gonna give a quick crash course for our application of it to our current problem.6\r\nAll you need to know here is that reduce() takes a vector as its first argument, a function as its second argument, and an optional .init argument.7\r\nHere’s a schematic:\r\n\r\n\r\n\r\nFigure 1: From Advanced R by Hadley Wickham\r\n\r\n\r\n\r\nLet me really quickly demonstrate reduce() in action.\r\nSay you wanted to add up the numbers 1 through 5, but only using the plus operator +. You could do something like this:8\r\n\r\n\r\n1 + 2 + 3 + 4 + 5\r\n\r\n\r\n [1] 15\r\n\r\nWhich is the same as this:\r\n\r\n\r\nlibrary(purrr)\r\nreduce(1:5, `+`)\r\n\r\n\r\n [1] 15\r\n\r\nAnd if you want the start value to be something that’s not the first argument of the vector, pass that to the .init argument:\r\n\r\n\r\nidentical(\r\n 0.5 + 1 + 2 + 3 + 4 + 5,\r\n reduce(1:5, `+`, .init = 0.5)\r\n)\r\n\r\n\r\n [1] TRUE\r\n\r\nIf you want to be specific, you can use an {rlang}-style anonymous function where .x is the accumulated value being passed into the first argument fo the function and .y is the second argument of the function.9\r\n\r\n\r\nidentical(\r\n reduce(1:5, `+`, .init = 0.5),\r\n reduce(1:5, ~ .x + .y, .init = 0.5)\r\n)\r\n\r\n\r\n [1] TRUE\r\n\r\nAnd two more examples just to demonstrate that directionality matters:\r\n\r\n\r\nidentical(\r\n reduce(1:5, `^`, .init = 0.5),\r\n reduce(1:5, ~ .x ^ .y, .init = 0.5) # .x on left, .y on right\r\n)\r\n\r\n\r\n [1] TRUE\r\n\r\nidentical(\r\n reduce(1:5, `^`, .init = 0.5),\r\n reduce(1:5, ~ .y ^ .x, .init = 0.5) # .y on left, .x on right\r\n)\r\n\r\n\r\n [1] FALSE\r\n\r\nThat’s pretty much all you need to know - let’s jump right in!\r\nExample 1: {ggplot2}\r\nA reduce() solution\r\nRecall that we had this sad code:\r\n\r\n\r\nggplot(mtcars, aes(hp, mpg)) + \r\n geom_point(size = 8, alpha = .5) +\r\n geom_point(size = 4, alpha = .5) +\r\n geom_point(size = 2, alpha = .5)\r\n\r\n\r\n\r\nFor illustrative purposes, I’m going to move the + “pipes” to the beginning of each line:\r\n\r\n\r\nggplot(mtcars, aes(hp, mpg))\r\n + geom_point(size = 8, alpha = .5)\r\n + geom_point(size = 4, alpha = .5)\r\n + geom_point(size = 2, alpha = .5)\r\n\r\n\r\n\r\nAt this point, we see a clear pattern emerge line-by-line. We start with ggplot(mtcars, aes(hp, mpg)), which is kind of its own thing. Then we have three repetitions of + geom_point(size = X, alpha = .5) where the X varies between 8, 4, and 2. We also notice that the sequence of calls goes from left to right, as is the normal order of piping.\r\nNow let’s translate these observations into reduce(). I’m bad with words so here’s a visual:\r\n\r\n\r\n\r\nLet’s go over what we did in our call to reduce() above:\r\nIn the first argument, we have the vector of values that are iterated over.\r\nIn the second argument, we have an anonymous function composed of…\r\nThe .x variable, which represents the accumulated value. In this context, we keep the .x on the left because that is the left-hand side that we are carrying over to the next call via the +.\r\nThe .y variable, which takes on values from the first argument passed into reduce(). In this context, .y will be each value of the numeric vector c(8, 4, 2) since .init is given.\r\nThe repeating function call geom_point(size = .y, alpha = .5) that is called with each value of the vector passed in as the first argument.\r\n\r\nIn the third argument .init, we have ggplot(mtcars, aes(hp, mpg)) which is the non-repeating piece of code that we start with.\r\nIf you want to see the actual code run, here it is:\r\n\r\n\r\nreduce(\r\n c(8, 4, 2),\r\n ~ .x + geom_point(size = .y, alpha = .5),\r\n .init = ggplot(mtcars, aes(hp, mpg))\r\n)\r\n\r\n\r\n\r\n\r\nLet’s dig in a bit more, this time with an example that looks prettier.\r\nSuppose you want to collapse the repeated calls to geom_point() in this code:\r\n\r\n\r\nviridis_colors <- viridis::viridis(10)\r\n\r\nmtcars %>% \r\n ggplot(aes(hp, mpg)) +\r\n geom_point(size = 20, color = viridis_colors[10]) +\r\n geom_point(size = 18, color = viridis_colors[9]) +\r\n geom_point(size = 16, color = viridis_colors[8]) +\r\n geom_point(size = 14, color = viridis_colors[7]) +\r\n geom_point(size = 12, color = viridis_colors[6]) +\r\n geom_point(size = 10, color = viridis_colors[5]) +\r\n geom_point(size = 8, color = viridis_colors[4]) +\r\n geom_point(size = 6, color = viridis_colors[3]) +\r\n geom_point(size = 4, color = viridis_colors[2]) +\r\n geom_point(size = 2, color = viridis_colors[1]) +\r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))\r\n\r\n\r\n\r\n\r\nYou can do this with reduce() in a couple ways:10\r\n\r\n\r\nMethod 1\r\nMethod 1: Move all the “constant” parts to .init, since the order of these layers don’t matter.\r\n\r\n\r\nreduce(\r\n 10L:1L,\r\n ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),\r\n \r\n .init = mtcars %>% \r\n ggplot(aes(hp, mpg)) +\r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))\r\n \r\n)\r\n\r\n\r\n\r\n\r\n\r\nMethod 2\r\nMethod 2: Use reduce() in place, with the help of the {magrittr} dot .\r\n\r\n\r\nmtcars %>% \r\n ggplot(aes(hp, mpg)) %>% \r\n \r\n reduce(\r\n 10L:1L,\r\n ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),\r\n .init = . #<- right here!\r\n ) +\r\n \r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))\r\n\r\n\r\n\r\n\r\n\r\nMethod 3\r\nMethod 3: Move all the “constant” parts to the top, wrap it in parentheses, and pass the whole thing into .init using the {magrittr} dot .\r\n\r\n\r\n(mtcars %>% \r\n ggplot(aes(hp, mpg)) +\r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))) %>% \r\n \r\n reduce(\r\n 10L:1L,\r\n ~ .x + geom_point(size = .y * 2, color = viridis_colors[.y]),\r\n .init = . #<- right here!\r\n )\r\n\r\n\r\n\r\n\r\n\r\nAll in all, we see that reduce() allows us to write more succinct code!\r\nAn obvious advantage to this is that it is now really easy to make a single change that applies to all the repeated calls.\r\nFor example, if I want to make the radius of the points grow/shrink exponentially, I just need to modify the anonymous function in the second argument of reduce():\r\n\r\n\r\n# Using Method 3\r\n(mtcars %>% \r\n ggplot(aes(hp, mpg)) +\r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))) %>% \r\n reduce(\r\n 10L:1L,\r\n ~ .x + geom_point(size = .y ^ 1.5, color = viridis_colors[.y]), # exponential!\r\n .init = .\r\n )\r\n\r\n\r\n\r\n\r\nYay, we collapsed ten layers of geom_point()!\r\nfeat. accumulate()\r\nThere’s actually one more thing I want to show here, which is holding onto intermediate values using accumulate().\r\naccumulate() is like reduce(), except instead of returning a single value which is the output of the very last function call, it keeps all intermediate values and returns them in a list.\r\n\r\n\r\naccumulate(1:5, `+`)\r\n\r\n\r\n [1] 1 3 6 10 15\r\n\r\nCheck out what happens if I change reduce() to accumulate() and return each element of the resulting list:\r\n\r\n\r\nplots <- (mtcars %>% \r\n ggplot(aes(hp, mpg)) +\r\n scale_x_discrete(expand = expansion(.2)) +\r\n scale_y_continuous(expand = expansion(.2)) +\r\n theme_void() +\r\n theme(panel.background = element_rect(fill = \"grey20\"))) %>% \r\n accumulate(\r\n 10L:1L,\r\n ~ .x + geom_point(size = .y ^ 1.5, color = viridis_colors[.y]),\r\n .init = .\r\n )\r\n\r\nfor (i in plots) { plot(i) }\r\n\r\n\r\n\r\n\r\nWe got back the intermediate plots!\r\nAre you thinking what I’m thinking? Let’s animate this!\r\n\r\n\r\nlibrary(magick)\r\n\r\n# change ggplot2 objects into images\r\nimgs <- map(1:length(plots), ~ {\r\n img <- image_graph(width = 672, height = 480)\r\n plot(plots[[.x]])\r\n dev.off()\r\n img\r\n})\r\n\r\n# combine images as frames\r\nimgs <- image_join(imgs)\r\n\r\n# animate\r\nimage_animate(imgs)\r\n\r\n\r\n\r\n\r\n\r\n\r\nNeat!11\r\nExample 2: {kableExtra}\r\nA reduce2() solution\r\nRecall that we had this sad code:\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% \r\n column_spec(3, background = \"skyblue\") %>% \r\n column_spec(4, background = \"forestgreen\") %>% \r\n column_spec(5, background = \"chocolate\")\r\n\r\n\r\n\r\nWe’ve got two things varying here: the column location 3:5 and the background color c(\"skyblue\", \"forestgreen\", \"chocolate\"). We could do the same trick I sneaked into the previous section by just passing one vector to reduce() that basically functions as an index:12\r\n\r\n\r\nnumbers <- 3:5\r\nbackground_colors <- c(\"skyblue\", \"forestgreen\", \"chocolate\")\r\n\r\n(mtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\")) %>% \r\n reduce(\r\n 1:3,\r\n ~ .x %>% column_spec(numbers[.y], background = background_colors[.y]),\r\n .init = .\r\n )\r\n\r\n\r\n\r\nBut I want to use this opportunity to showcase reduce2(), which explicitly takes a second varying argument to the function that you are reduce()-ing over.\r\nHere, ..1 is like the .x and ..2 is like the .y from reduce(). The only new part is ..3 which refers to the second varying argument.\r\n\r\n\r\n(mtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\")) %>% \r\n reduce2(\r\n 3:5, # 1st varying argument (represented by ..2)\r\n c(\"skyblue\", \"forestgreen\", \"chocolate\"), # 2nd varying argument (represented by ..3)\r\n ~ ..1 %>% column_spec(..2, background = ..3),\r\n .init = .\r\n )\r\n\r\n\r\n\r\nWe’re not done yet! We can actually skip the {magrittr} pipe %>% and just stick ..1 as the first argument inside column_spec().13 This actually improves performance because you’re removing the overhead from evaluating the pipe!\r\nAdditionally, because the pipe forces evaluation with each call unlike + in {ggplot2}, we don’t need the parantheses wrapped around the top part of the code for the {magrittr} dot . to work!\r\nHere is the final reduce2() solution for our sad code:\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% # No need to wrap in parentheses!\r\n reduce2(\r\n 3:5, \r\n c(\"skyblue\", \"forestgreen\", \"chocolate\"), \r\n ~ column_spec(..1, ..2, background = ..3), # No need for the pipe!\r\n .init = .\r\n )\r\n\r\n\r\n\r\n\r\n\r\nmpg\r\n\r\n\r\ncyl\r\n\r\n\r\ndisp\r\n\r\n\r\nhp\r\n\r\n\r\ndrat\r\n\r\n\r\nwt\r\n\r\n\r\nqsec\r\n\r\n\r\nvs\r\n\r\n\r\nam\r\n\r\n\r\ngear\r\n\r\n\r\ncarb\r\n\r\n\r\nMazda RX4\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.620\r\n\r\n\r\n16.46\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nMazda RX4 Wag\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.875\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nDatsun 710\r\n\r\n\r\n22.8\r\n\r\n\r\n4\r\n\r\n\r\n108\r\n\r\n\r\n93\r\n\r\n\r\n3.85\r\n\r\n\r\n2.320\r\n\r\n\r\n18.61\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\nHornet 4 Drive\r\n\r\n\r\n21.4\r\n\r\n\r\n6\r\n\r\n\r\n258\r\n\r\n\r\n110\r\n\r\n\r\n3.08\r\n\r\n\r\n3.215\r\n\r\n\r\n19.44\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nHornet Sportabout\r\n\r\n\r\n18.7\r\n\r\n\r\n8\r\n\r\n\r\n360\r\n\r\n\r\n175\r\n\r\n\r\n3.15\r\n\r\n\r\n3.440\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\nValiant\r\n\r\n\r\n18.1\r\n\r\n\r\n6\r\n\r\n\r\n225\r\n\r\n\r\n105\r\n\r\n\r\n2.76\r\n\r\n\r\n3.460\r\n\r\n\r\n20.22\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nAnd of course, we now have the flexibilty to do much more complicated manipulations!\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% \r\n reduce2(\r\n 1:12, \r\n viridis::viridis(12), \r\n ~ column_spec(..1, ..2, background = ..3, color = if(..2 < 5){\"white\"}),\r\n .init = .\r\n )\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nmpg\r\n\r\n\r\ncyl\r\n\r\n\r\ndisp\r\n\r\n\r\nhp\r\n\r\n\r\ndrat\r\n\r\n\r\nwt\r\n\r\n\r\nqsec\r\n\r\n\r\nvs\r\n\r\n\r\nam\r\n\r\n\r\ngear\r\n\r\n\r\ncarb\r\n\r\n\r\nMazda RX4\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.620\r\n\r\n\r\n16.46\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nMazda RX4 Wag\r\n\r\n\r\n21.0\r\n\r\n\r\n6\r\n\r\n\r\n160\r\n\r\n\r\n110\r\n\r\n\r\n3.90\r\n\r\n\r\n2.875\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n4\r\n\r\n\r\nDatsun 710\r\n\r\n\r\n22.8\r\n\r\n\r\n4\r\n\r\n\r\n108\r\n\r\n\r\n93\r\n\r\n\r\n3.85\r\n\r\n\r\n2.320\r\n\r\n\r\n18.61\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\n1\r\n\r\n\r\nHornet 4 Drive\r\n\r\n\r\n21.4\r\n\r\n\r\n6\r\n\r\n\r\n258\r\n\r\n\r\n110\r\n\r\n\r\n3.08\r\n\r\n\r\n3.215\r\n\r\n\r\n19.44\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nHornet Sportabout\r\n\r\n\r\n18.7\r\n\r\n\r\n8\r\n\r\n\r\n360\r\n\r\n\r\n175\r\n\r\n\r\n3.15\r\n\r\n\r\n3.440\r\n\r\n\r\n17.02\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n2\r\n\r\n\r\nValiant\r\n\r\n\r\n18.1\r\n\r\n\r\n6\r\n\r\n\r\n225\r\n\r\n\r\n105\r\n\r\n\r\n2.76\r\n\r\n\r\n3.460\r\n\r\n\r\n20.22\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n3\r\n\r\n\r\n1\r\n\r\n\r\nfeat. accumulate2()\r\nYep, that’s right - more animations with accumulate() and {magick}!\r\nActually, to be precise, we’re going to use the accumuate2() here to replace our reduce2().\r\nFirst, we save the list of intermediate outputs to tables:\r\n\r\n\r\ntables <- mtcars %>% \r\n head() %>% \r\n kbl() %>% \r\n kable_classic(html_font = \"Roboto\") %>% \r\n kable_styling(full_width = FALSE) %>% # Added to keep aspect ratio constant when saving\r\n accumulate2(\r\n 1:(length(mtcars)+1), \r\n viridis::viridis(length(mtcars)+1), \r\n ~ column_spec(..1, ..2, background = ..3, color = if(..2 < 5){\"white\"}),\r\n .init = .\r\n )\r\n\r\n\r\n\r\nThen, we save each table in tables as an image:\r\n\r\n\r\niwalk(tables, ~ save_kable(.x, file = here::here(\"img\", paste0(\"table\", .y, \".png\")), zoom = 2))\r\n\r\n\r\n\r\nFinally, we read them in and animate:\r\n\r\n\r\ntables <- map(\r\n paste0(\"table\", 1:length(tables), \".png\"),\r\n ~ image_read(here::here(\"img\", .x))\r\n)\r\n\r\ntables <- image_join(tables)\r\n\r\nimage_animate(tables)\r\n\r\n\r\n\r\n\r\n\r\n\r\nBet you don’t see animated tables often!\r\nExample 3: {dplyr}\r\nA reduce() solution\r\nRecall that we had this sad code:\r\n\r\n\r\nnew_cols <- c(\"a\", \"b\", \"c\")\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n mutate(!!new_cols[1] := NA) %>% \r\n mutate(!!new_cols[2] := NA) %>% \r\n mutate(!!new_cols[3] := NA)\r\n\r\n\r\n mpg a b c\r\n 1 21.0 NA NA NA\r\n 2 21.0 NA NA NA\r\n 3 22.8 NA NA NA\r\n 4 21.4 NA NA NA\r\n 5 18.7 NA NA NA\r\n 6 18.1 NA NA NA\r\n\r\nYou know the drill - a simple call to reduce() gives us three new columns with names corresponding to the elements of the new_cols character vector we defined above:\r\n\r\n\r\n# Converting to tibble for nicer printing\r\nmtcars <- as_tibble(mtcars)\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n reduce(\r\n new_cols,\r\n ~ mutate(.x, !!.y := NA),\r\n .init = .\r\n )\r\n\r\n\r\n # A tibble: 6 x 4\r\n mpg a b c \r\n \r\n 1 21 NA NA NA \r\n 2 21 NA NA NA \r\n 3 22.8 NA NA NA \r\n 4 21.4 NA NA NA \r\n 5 18.7 NA NA NA \r\n 6 18.1 NA NA NA\r\n\r\nAgain, this gives you a lot of flexibility, like the ability to dynamically assign values to each new column:\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n reduce(\r\n new_cols,\r\n ~ mutate(.x, !!.y := paste0(.y, \"-\", row_number())),\r\n .init = .\r\n )\r\n\r\n\r\n # A tibble: 6 x 4\r\n mpg a b c \r\n \r\n 1 21 a-1 b-1 c-1 \r\n 2 21 a-2 b-2 c-2 \r\n 3 22.8 a-3 b-3 c-3 \r\n 4 21.4 a-4 b-4 c-4 \r\n 5 18.7 a-5 b-5 c-5 \r\n 6 18.1 a-6 b-6 c-6\r\n\r\nWe can take this even further using context dependent expressions like cur_data(), and do something like keeping track of the columns present at each point a new column has been created via mutate():\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n reduce(\r\n new_cols,\r\n ~ mutate(.x, !!.y := paste(c(names(cur_data()), .y), collapse = \"-\")),\r\n .init = .\r\n )\r\n\r\n\r\n # A tibble: 6 x 4\r\n mpg a b c \r\n \r\n 1 21 mpg-a mpg-a-b mpg-a-b-c\r\n 2 21 mpg-a mpg-a-b mpg-a-b-c\r\n 3 22.8 mpg-a mpg-a-b mpg-a-b-c\r\n 4 21.4 mpg-a mpg-a-b mpg-a-b-c\r\n 5 18.7 mpg-a mpg-a-b mpg-a-b-c\r\n 6 18.1 mpg-a mpg-a-b mpg-a-b-c\r\n\r\nHere’s another example just for fun - an “addition matrix”:14\r\n\r\n\r\nmtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n reduce(\r\n pull(., mpg),\r\n ~ mutate(.x, !!as.character(.y) := .y + mpg),\r\n .init = .\r\n )\r\n\r\n\r\n # A tibble: 6 x 6\r\n mpg `21` `22.8` `21.4` `18.7` `18.1`\r\n \r\n 1 21 42 43.8 42.4 39.7 39.1\r\n 2 21 42 43.8 42.4 39.7 39.1\r\n 3 22.8 43.8 45.6 44.2 41.5 40.9\r\n 4 21.4 42.4 44.2 42.8 40.1 39.5\r\n 5 18.7 39.7 41.5 40.1 37.4 36.8\r\n 6 18.1 39.1 40.9 39.5 36.8 36.2\r\n\r\nLet’s now look at a more practical application of this: explicit dummy coding!\r\nIn R, the factor data structure allows implicit dummy coding, which you can access using contrasts().\r\nHere, in our data penguins from the {palmerpenguins} package, we see that the 3-way contrast between “Adelie”, “Chinstrap”, and “Gentoo” in the species factor column is treatment coded, with “Adelie” set as the reference level:\r\n\r\n\r\ndata(\"penguins\", package = \"palmerpenguins\")\r\n\r\npenguins_implicit <- penguins %>% \r\n na.omit() %>% \r\n select(species, flipper_length_mm) %>% \r\n mutate(species = factor(species))\r\n\r\ncontrasts(penguins_implicit$species)\r\n\r\n\r\n Chinstrap Gentoo\r\n Adelie 0 0\r\n Chinstrap 1 0\r\n Gentoo 0 1\r\n\r\nWe can also infer that from the output of this simple linear model:15\r\n\r\n\r\nbroom::tidy(lm(flipper_length_mm ~ species, data = penguins_implicit))\r\n\r\n\r\n # A tibble: 3 x 5\r\n term estimate std.error statistic p.value\r\n \r\n 1 (Intercept) 190. 0.552 344. 0. \r\n 2 speciesChinstrap 5.72 0.980 5.84 1.25e- 8\r\n 3 speciesGentoo 27.1 0.824 32.9 2.68e-106\r\n\r\nWhat’s cool is that you can make this 3-way treatment coding explicit by expanding the matrix into actual columns of the data!\r\nHere’s a reduce() solution:\r\n\r\n\r\npenguins_explicit <- \r\n reduce(\r\n levels(penguins_implicit$species)[-1],\r\n ~ mutate(.x, !!paste0(\"species\", .y) := as.integer(species == .y)),\r\n .init = penguins_implicit\r\n )\r\n\r\n\r\n\r\n\r\n\r\n\r\nspecies\r\n\r\n\r\nflipper_length_mm\r\n\r\n\r\nspeciesChinstrap\r\n\r\n\r\nspeciesGentoo\r\n\r\n\r\nAdelie\r\n\r\n\r\n181\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n181\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n182\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n198\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n197\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n194\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n174\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n180\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n180\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n183\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n172\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n180\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n178\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n178\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n188\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n180\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n181\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n182\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n182\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n188\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n200\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n181\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n194\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n192\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n192\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n188\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n198\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n197\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n194\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n202\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n205\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n178\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n192\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n192\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n203\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n183\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n199\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n181\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n197\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n198\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n197\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n196\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n188\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n199\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n189\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n198\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n176\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n202\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n186\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n199\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n197\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n199\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n191\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n200\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n188\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n192\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n185\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n190\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n184\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n195\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n193\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n187\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nAdelie\r\n\r\n\r\n201\r\n\r\n\r\n0\r\n\r\n\r\n0\r\n\r\n\r\nGentoo\r\n\r\n\r\n211\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n218\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n211\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n219\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n209\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n214\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n214\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n217\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n221\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n209\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n218\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n209\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n207\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n219\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n225\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n217\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n225\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n225\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n217\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n224\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n221\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n214\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n231\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n219\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n229\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n223\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n221\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n221\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n217\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n209\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n220\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n223\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n221\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n224\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n228\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n218\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n218\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n218\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n228\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n224\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n214\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n226\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n203\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n225\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n219\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n228\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n228\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n210\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n219\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n208\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n209\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n216\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n229\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n217\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n230\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n214\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n215\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n222\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n212\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nGentoo\r\n\r\n\r\n213\r\n\r\n\r\n0\r\n\r\n\r\n1\r\n\r\n\r\nChinstrap\r\n\r\n\r\n192\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n196\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n193\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n188\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n197\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n198\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n178\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n197\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n198\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n193\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n194\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n185\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n201\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n190\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n201\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n197\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n181\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n190\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n181\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n191\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n193\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n197\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n200\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n200\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n191\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n205\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n201\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n203\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n199\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n210\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n192\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n205\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n210\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n196\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n196\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n196\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n201\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n190\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n212\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n198\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n199\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n201\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n193\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n203\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n187\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n197\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n191\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n203\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n202\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n194\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n206\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n189\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n195\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n207\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n202\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n193\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n210\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\nChinstrap\r\n\r\n\r\n198\r\n\r\n\r\n1\r\n\r\n\r\n0\r\n\r\n\r\n\r\nAnd we get the exact same output from lm() when we throw in the new columns speciesChinstrap and speciesGentoo as the predictors!\r\n\r\n\r\nbroom::tidy(lm(flipper_length_mm ~ speciesChinstrap + speciesGentoo, data = penguins_explicit))\r\n\r\n\r\n # A tibble: 3 x 5\r\n term estimate std.error statistic p.value\r\n \r\n 1 (Intercept) 190. 0.552 344. 0. \r\n 2 speciesChinstrap 5.72 0.980 5.84 1.25e- 8\r\n 3 speciesGentoo 27.1 0.824 32.9 2.68e-106\r\n\r\nBy the way, if you’re wondering how this is practical, some modeling packages in R (like {lavaan} for structural equation modeling) only accept dummy coded variables that exist as independent columns/vectors, not as a metadata of a factor vector.16 This is common enough that some packages like {psych} have a function that does the same transformation we just did, called dummy.code()17:\r\n\r\n\r\nbind_cols(\r\n penguins_implicit,\r\n psych::dummy.code(penguins_implicit$species)\r\n)\r\n\r\n\r\n # A tibble: 333 x 3\r\n species flipper_length_mm ...3[,\"Adelie\"] [,\"Gentoo\"] [,\"Chinstrap\"]\r\n \r\n 1 Adelie 181 1 0 0\r\n 2 Adelie 186 1 0 0\r\n 3 Adelie 195 1 0 0\r\n 4 Adelie 193 1 0 0\r\n 5 Adelie 190 1 0 0\r\n 6 Adelie 181 1 0 0\r\n 7 Adelie 195 1 0 0\r\n 8 Adelie 182 1 0 0\r\n 9 Adelie 191 1 0 0\r\n 10 Adelie 198 1 0 0\r\n # ... with 323 more rows\r\n\r\nfeat. {data.table}\r\nOf course, you could do all of this without reduce() in {data.table} because its walrus := is vectorized.\r\nHere’s the {data.table} solution for our sad code:\r\n\r\n\r\nlibrary(data.table)\r\nnew_cols <- c(\"a\", \"b\", \"c\")\r\n\r\nmtcars_dt <- mtcars %>% \r\n head() %>% \r\n select(mpg) %>% \r\n as.data.table()\r\n\r\nmtcars_dt[, (new_cols) := NA][]\r\n\r\n\r\n mpg a b c\r\n 1: 21.0 NA NA NA\r\n 2: 21.0 NA NA NA\r\n 3: 22.8 NA NA NA\r\n 4: 21.4 NA NA NA\r\n 5: 18.7 NA NA NA\r\n 6: 18.1 NA NA NA\r\n\r\nAnd here’s a {data.table} solution for the explicit dummy coding example:\r\n\r\n\r\npenguins_dt <- as.data.table(penguins_implicit)\r\n\r\ntreatment_lvls <- levels(penguins_dt$species)[-1]\r\ntreatment_cols <- paste0(\"species\", treatment_lvls)\r\n\r\npenguins_dt[, (treatment_cols) := lapply(treatment_lvls, function(x){as.integer(species == x)})][]\r\n\r\n\r\n species flipper_length_mm speciesChinstrap speciesGentoo\r\n 1: Adelie 181 0 0\r\n 2: Adelie 186 0 0\r\n 3: Adelie 195 0 0\r\n 4: Adelie 193 0 0\r\n 5: Adelie 190 0 0\r\n --- \r\n 329: Chinstrap 207 1 0\r\n 330: Chinstrap 202 1 0\r\n 331: Chinstrap 193 1 0\r\n 332: Chinstrap 210 1 0\r\n 333: Chinstrap 198 1 0\r\n\r\nI personally default to using {data.table} over {dplyr} in these cases.\r\nMisc.\r\nYou can also pass in a list of functions instead of a list of arguments because why not.\r\nFor example, this replicates the very first code I showed in this blog post:\r\n\r\n\r\nmy_funs <- list(deviation, square, mean, sqrt)\r\n\r\nreduce(\r\n my_funs,\r\n ~ .y(.x),\r\n .init = nums\r\n)\r\n\r\n\r\n [1] 0.3039881\r\n\r\nYou could also pass in both a list of functions and a list of their arguments if you really want to abstract away from, like, literally everything:\r\n\r\n\r\nLawful Good\r\n\r\n\r\nlibrary(janitor)\r\n\r\nmtcars %>% \r\n clean_names(case = \"title\") %>% \r\n tabyl(2) %>% \r\n adorn_rounding(digits = 2) %>% \r\n adorn_totals()\r\n\r\n\r\n Cyl n percent\r\n 4 11 0.34\r\n 6 7 0.22\r\n 8 14 0.44\r\n Total 32 1.00\r\n\r\n\r\n\r\nChaotic Evil\r\n\r\n\r\njanitor_funs <- list(clean_names, tabyl, adorn_rounding, adorn_totals)\r\njanitor_args <- list(list(case = \"title\"), list(2), list(digits = 2), NULL)\r\n\r\nreduce2(\r\n janitor_funs,\r\n janitor_args,\r\n ~ do.call(..2, c(list(dat = ..1), ..3)),\r\n .init = mtcars\r\n)\r\n\r\n\r\n Cyl n percent\r\n 4 11 0.34\r\n 6 7 0.22\r\n 8 14 0.44\r\n Total 32 1.00\r\n\r\n\r\n\r\nHave fun reducing repetitions in your code with reduce()!\r\n\r\nSo much so that there’s going to be a native pipe operator!↩︎\r\nTaken from Advanced R Ch. 6↩︎\r\nIf you aren’t familiar with {kableExtra}, you just need to know that column_spec() can take a column index as its first argument and a color as the background argument to set the background color of a column to the provided color. And as we see here, if a color vector is passed into background, it’s just recycled to color the rows which is not what we want.↩︎\r\nIf this is your first time seeing the “bang bang” !! operator and the “walrus” := operator being used this way, check out the documentation on quasiquotation.↩︎\r\nFor those of you more familiar with quasiquation in {dplyr}, I should also mention that using “big bang” !!! like in mutate(!!!new_cols := NA) doesn’t work either. As far as I know, := is just an alias of = for the {rlang} parser, and as we know = cannot assign more than one variable at once (unlike Python, for example), which explains the error.↩︎\r\nNote that there are more motivated usescases of reduce() out there, mostly in doing mathy-things, and I’m by no means advocating that you should always use reduce() in our context - I just think it’s fun to play around with!↩︎\r\nThere’s also .dir argument that allows you to specify the direction, but not relevant here because when you pipe, the left-hand side is always the first input to the next function.↩︎\r\nIf it helps, think of it like ((((1 + 2) + 3) + 4) + 5)↩︎\r\nThe function passed into reduce() doesn’t have to be in {rlang} anonymous function syntax, but I like it so I’ll keep using it here.↩︎\r\nBy the way, we could also do this with purrr::map() since multiple ggplot2 layers can be stored into a list and added all together in one step. But then we can’t do this cool thing I’m going to show with accumulate() next!↩︎\r\nBy the way, if you want a whole package dedicated to animating and incrementally building {ggplot2} code, check out @EvaMaeRey’s {flipbookr} package!↩︎\r\nWe are still “iterating” over the numbers and background_colors vectors but in a round-about way by passing a vector of indices for reduce() to iterate over instead and using the indices to access elements of the two vectors. This actually seems like the way to go when you have more than two varying arguments because there’s no pmap() equavalent for reduce() like preduce().↩︎\r\nNote that we couldn’t do this with + in our {ggplot2} example because geom_point() doesn’t take a ggplot object as its first argument. Basically, the + operator is re-purposed as a class method for ggplot objects but it’s kinda complicated so that’s all I’ll say about that.↩︎\r\nNote the use of as.character() to make sure that the left-hand side of the walrus := is converted from numeric to character. Alternatively, using the new glue syntax support from dplyr > 1.0.0, we can simplify !!as.character(.y) := to \"{.y}\" :=↩︎\r\nIf you aren’t familiar with linear models in R, we know that “Adelie” is the reference level because there is no “speciesAdelie” term. The estimate for “Adelie” is represented by the “(Intercept)”!↩︎\r\nFiguring this out has caused some headaches and that’s what I get for not carefully reading the docs↩︎\r\nExcept dummy.code() also returns a column for the reference level whose value is always 1, which is kinda pointless↩︎\r\n", + "preview": "posts/2020-12-13-collapse-repetitive-piping-with-reduce/reduce_ggplot.png", + "last_modified": "2021-01-18T21:20:07-05:00", + "input_file": {}, + "preview_width": 1233, + "preview_height": 775 + }, + { + "path": "posts/2020-11-08-plot-makeover-2/", + "title": "Plot Makeover #2", + "description": "Making a dodged-stacked hybrid bar plot in {ggplot2}", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-11-08", + "categories": [ + "plot makeover", + "data visualization", + "ggplot2" + ], + "contents": "\r\n\r\nContents\r\nBefore\r\nMy Plan\r\nAfter\r\nFirst draft\r\nFinal touch-up\r\n\r\n\r\n\r\n\r\n\r\nThis is the second installment of plot makeover where I take a plot in the wild and make very opinionated modifications to it.\r\nBefore\r\nOur plot-in-the-wild comes from (Yurovsky and Yu 2008), a paper on statistical word learning. The plot that I’ll be looking at here is Figure 2, a bar plot of accuracy in a 3-by-3 experimental design.\r\n\r\n\r\n\r\nFigure 1: Plot from Yurovsky and Yu (2008)\r\n\r\n\r\n\r\nAs you might notice, there’s something interesting going on in this bar plot. It looks like the red and green bars stack together but dodge from the blue bar. It’s looks a bit weird for me as someone who mainly uses {ggplot2} because this kind of a hybrid design is not explicitly supported in the API.\r\nFor this plot makeover, I’ll leave aside the issue of whether having a half-stacked, half-dodged bar plot is a good idea.1 In fact, I’m not even gonna focus much on the “makeover” part. Instead I’m just going to take a shot at recreating this plot (likely made in MATLAB with post-processing in PowerPoint) in {ggplot2}.\r\nMy Plan\r\nAgain, my primary goal here is replication. But I do want to touch up on some aesthetics while I’m at it.\r\nMajor Changes:\r\nMove the title to above the plot\r\nMove the legend inside the plot\r\nMove/remove the y-axis title so it’s not vertically aligned\r\nMinor Changes:\r\nRemove grid lines\r\nPut y-axis in percentages\r\nAdd white borders around the bars for clearer color contrast\r\nAfter\r\nFirst draft\r\nFor a first pass on the makeover, I wanted to get the hybrid design right.\r\nThe plot below isn’t quite there in terms of covering everything I laid out in my plan, but it does replicate the bar plot design specifically.\r\n\r\n\r\nPlot\r\n\r\n\r\n\r\n\r\n\r\nCode\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(extrafont)\r\n\r\ndf <- tribble(\r\n ~Condition, ~Referent, ~Accuracy,\r\n \"Primacy\", \"Single\", 0.63,\r\n \"Primacy\", \"Primacy\", 0.59,\r\n \"Recency\", \"Single\", 0.63,\r\n \"Recency\", \"Recency\", 0.5,\r\n \"Both\", \"Single\", 0.63,\r\n \"Both\", \"Primacy\", 0.5,\r\n \"Both\", \"Recency\", 0.31\r\n) %>% \r\n mutate(\r\n error_low = runif(7, .04, .06),\r\n error_high = runif(7, .04, .06),\r\n Condition_name = factor(Condition, levels = c(\"Primacy\", \"Recency\", \"Both\")),\r\n Condition = as.numeric(Condition_name),\r\n Referent = factor(Referent, levels = c(\"Single\", \"Recency\", \"Primacy\")),\r\n left = Referent == \"Single\",\r\n color = case_when(\r\n Referent == \"Single\" ~ \"#29476B\",\r\n Referent == \"Primacy\" ~ \"#AD403D\",\r\n Referent == \"Recency\" ~ \"#9BBB58\"\r\n )\r\n )\r\n\r\n\r\nggplot(mapping = aes(x = Condition, y = Accuracy, fill = color)) +\r\n geom_col(\r\n data = filter(df, left),\r\n width = .3,\r\n color = \"white\",\r\n position = position_nudge(x = -.3)\r\n ) +\r\n geom_errorbar(\r\n aes(ymin = Accuracy - error_low, ymax = Accuracy + error_high),\r\n data = filter(df, left),\r\n width = .1,\r\n position = position_nudge(x = -.3)\r\n ) +\r\n geom_col(\r\n data = filter(df, !left),\r\n color = \"white\",\r\n width = .3,\r\n ) +\r\n geom_errorbar(\r\n aes(y = y, ymin = y - error_low, ymax = y + error_high),\r\n data = filter(df, !left) %>% \r\n group_by(Condition) %>% \r\n mutate(y = accumulate(Accuracy, sum)),\r\n width = .1\r\n ) +\r\n scale_fill_identity(\r\n labels = levels(df$Referent),\r\n guide = guide_legend(title = \"Referent\")\r\n ) +\r\n scale_x_continuous(\r\n breaks = 1:3 - .15,\r\n labels = levels(df$Condition_name),\r\n expand = expansion(.1)\r\n ) +\r\n scale_y_continuous(\r\n breaks = scales::pretty_breaks(6),\r\n labels = str_remove(scales::pretty_breaks(6)(0:1), \"\\\\.0+\"),\r\n limits = 0:1,\r\n expand = expansion(0)\r\n ) +\r\n labs(\r\n title = \"Exp1: Accuracy by Condition and Word Type\"\r\n ) +\r\n theme_classic(\r\n base_family = \"Roboto\",\r\n base_size = 16\r\n )\r\n\r\n\r\n\r\n\r\n\r\nAs you might guess from my two calls to geom_col() and geom_errorbar(), I actually split the plotting of the bars into two parts. First I drew the blue bars and their errorbars, then I drew the green and red bars and their errorbars.\r\nEffectively, the above plot is a combination of these two:2\r\n\r\n\r\n\r\nA bit hacky, I guess, but it works!\r\n\r\n\r\n\r\n\r\nFinal touch-up\r\n\r\n\r\n\r\n\r\n\r\nggplot(mapping = aes(x = Condition, y = Accuracy, fill = color)) +\r\n geom_col(\r\n data = filter(df, left),\r\n width = .3,\r\n color = \"white\",\r\n position = position_nudge(x = -.3),\r\n ) +\r\n geom_errorbar(\r\n aes(ymin = Accuracy - error_low, ymax = Accuracy + error_high),\r\n data = filter(df, left),\r\n width = .1,\r\n position = position_nudge(x = -.3)\r\n ) +\r\n geom_col(\r\n data = filter(df, !left),\r\n color = \"white\",\r\n width = .3, \r\n ) +\r\n geom_errorbar(\r\n aes(y = y, ymin = y - error_low, ymax = y + error_high),\r\n data = filter(df, !left) %>% \r\n group_by(Condition) %>% \r\n mutate(y = accumulate(Accuracy, sum)),\r\n width = .1\r\n ) +\r\n geom_hline(\r\n aes(yintercept = .25),\r\n linetype = 2,\r\n size = 1,\r\n ) +\r\n geom_text(\r\n aes(x = 3.4, y = .29),\r\n label = \"Chance\",\r\n family = \"Adelle\",\r\n color = \"grey20\",\r\n inherit.aes = FALSE\r\n ) +\r\n scale_fill_identity(\r\n labels = c(\"Single\", \"Primacy\", \"Recency\"),\r\n guide = guide_legend(\r\n title = NULL,\r\n direction = \"horizontal\",\r\n override.aes = list(fill = c(\"#29476B\", \"#AD403D\", \"#9BBB58\"))\r\n )\r\n ) +\r\n scale_x_continuous(\r\n breaks = 1:3 - .15,\r\n labels = levels(df$Condition_name),\r\n expand = expansion(c(.1, .05))\r\n ) +\r\n scale_y_continuous(\r\n breaks = scales::pretty_breaks(6),\r\n labels = scales::percent_format(1),\r\n limits = 0:1,\r\n expand = expansion(0)\r\n ) +\r\n labs(\r\n title = \"Accuracy by Condition and Referent\",\r\n y = NULL\r\n ) +\r\n theme_classic(\r\n base_family = \"Roboto\",\r\n base_size = 16\r\n ) +\r\n theme(\r\n plot.title.position = \"plot\",\r\n plot.title = element_text(\r\n family = \"Roboto Slab\",\r\n margin = margin(0, 0, 1, 0, \"cm\")\r\n ),\r\n legend.position = c(.35, .9),\r\n axis.title.x = element_text(margin = margin(t = .4, unit = \"cm\")),\r\n plot.margin = margin(1, 1, .7, 1, \"cm\")\r\n )\r\n\r\n\r\n\r\n\r\n\r\n\r\nYurovsky, Daniel, and C. Yu. 2008. Mutual Exclusivity in Cross-Situational Statistical Learning. https://dll.sitehost.iu.edu/papers/Yurovsky_cs08.pdf.\r\n\r\n\r\nI actually don’t even have a strong feeling about this. It does look kinda cool.↩︎\r\nI used a neat trick from the R Markdown Cookbook to get the plots printed side-by-side↩︎\r\n", + "preview": "posts/2020-11-08-plot-makeover-2/plot-makeover-2_files/figure-html5/final-1.png", + "last_modified": "2021-06-11T03:45:52-04:00", + "input_file": {}, + "preview_width": 1344, + "preview_height": 1152 + }, + { + "path": "posts/2020-11-03-tidytuesday-2020-week-45/", + "title": "TidyTuesday 2020 week 45", + "description": "Waffle chart of IKEA furnitures in stock", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-11-03", + "categories": [ + "ggplot2", + "data visualization", + "tidytuesday" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n\r\n\r\n\r\nThings I learned\r\nHow to make waffle charts with {waffle} (finally!)\r\nUsing {patchwork} for a large list of plots using wrap_plots() and theme styling inside plot_annotation()\r\nWorking with a long canvas using the cairo_pdf() device\r\nUsing {ggfittext} for dynamically re-sizing annotations.\r\nThings to improve\r\nCouldn’t figure out background color for the entire visual and white ended up looking a bit too harsh on the eye\r\nIdeally would like to replace the squares with icons. Maybe I could’ve pursued that if I only plotted a couple furnitures.\r\nThe plot ended up being a bit too long. Again could’ve cut down a bit there, but I don’t mind it for this submission because I was more focused on learning how to make waffle charts at all.\r\nOops forgot to put in the data source\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(waffle)\r\nlibrary(extrafont)\r\nlibrary(patchwork)\r\n\r\ntuesdata <- tidytuesdayR::tt_load(2020, week = 45)\r\n\r\nikea_counts <- tuesdata$ikea %>% \r\n count(category) %>% \r\n mutate(n = round(n/5)) %>% \r\n arrange(-n)\r\n\r\nikea_colors <- c(nord::nord_palettes$algoma_forest, dutchmasters::dutchmasters_pal()(13)[-c(1, 8, 12)])\r\n\r\nikea_waffles <- map(1:nrow(ikea_counts), ~ {\r\n df <- slice(ikea_counts, .x)\r\n ggplot(df) +\r\n geom_waffle(\r\n aes(fill = category, values = n),\r\n n_rows = 20,\r\n size = 1.5,\r\n flip = TRUE,\r\n show.legend = FALSE\r\n ) +\r\n scale_fill_manual(values = ikea_colors[.x]) +\r\n ggfittext::geom_fit_text(\r\n aes(xmin = -15, xmax = -5, ymin = .5, ymax = .5 + ceiling(df$n/20), label = category),\r\n size = 54, grow = FALSE, fullheight = FALSE, place = \"left\" ,\r\n family = \"Roboto Slab\", fontface = \"bold\"\r\n ) +\r\n coord_equal(xlim = c(-16, 21)) +\r\n theme_void()\r\n})\r\n\r\nlegend_key <- ggplot() +\r\n annotation_custom(rectGrob(0.5, 0.5, height = .02, width = .02, gp = gpar(fill = \"grey50\", color = \"black\", lwd = 1))) +\r\n annotation_custom(textGrob(\"= 5 units\", gp = gpar(fontfamily = \"Roboto Slab\", fontface = \"bold\", fontsize = 12)), 3, 2.6) +\r\n coord_equal(xlim = c(0, 5), ylim = c(0, 5)) +\r\n theme_void()\r\n\r\npatched <- wrap_plots(ikea_waffles, ncol = 1) +\r\n plot_annotation(\r\n title = \"IKEA<\/span> Furnitures in Stock<\/span>\",\r\n caption = \"@yjunechoe\",\r\n theme = theme(\r\n plot.title = ggtext::element_markdown(\r\n size = 100,\r\n family = \"Noto\",\r\n face = \"bold\",\r\n hjust = .5,\r\n margin = margin(t = 1.5, b = 2, unit = \"in\")\r\n ),\r\n plot.caption = element_text(\r\n size = 32,\r\n family = \"IBM Plex Mono\",\r\n face = \"bold\",\r\n margin = margin(t = 1, b = 1, unit = \"in\")\r\n ),\r\n plot.margin = margin(2, 2, 2, 2, unit = \"in\")\r\n )\r\n ) &\r\n theme(plot.margin = margin(t = .5, b = .5, unit = \"in\")) \r\n\r\n\r\nggsave(\"tidytuesday_2020_45.pdf\", patched, device = cairo_pdf, scale = 2, width = 12, height = 26, limitsize = FALSE)\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-11-03-tidytuesday-2020-week-45/preview.png", + "last_modified": "2020-12-19T09:05:08-05:00", + "input_file": {}, + "preview_width": 4443, + "preview_height": 2950 + }, + { + "path": "posts/2020-10-28-tidytuesday-2020-week-44/", + "title": "TidyTuesday 2020 week 44", + "description": "Patched animation of the location and cumulative capacity of wind turbines in Canada", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-10-28", + "categories": [ + "ggplot2", + "gganimate", + "spatial", + "data visualization", + "tidytuesday" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n\r\n\r\n\r\nThings I learned\r\nUsing {magick} for animation composition, thanks to the {gganimate} wiki\r\nThe very basics of working with spatial data with {rnaturalearth} and {sf}1\r\nA bit about color schemes for maps (I particularly love this color as a way of de-emphasizing territories in the background)\r\nThings to improve\r\nI couldn’t figure out how to add margins to the bottom, but I now realize that I could’ve just played around with expansion() for the y-axis of the bar animation plot.\r\nImage composition took a while to render, which was a bit frustrating. Need to find a way to speed that up.\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(gganimate)\r\nlibrary(extrafont)\r\n\r\ntuesdata <- tidytuesdayR::tt_load(2020, week = 44)\r\n\r\nwind_turbine <- tuesdata$`wind-turbine` %>% \r\n select(\r\n ID = objectid,\r\n Province = province_territory,\r\n Capacity = total_project_capacity_mw,\r\n Diameter = rotor_diameter_m,\r\n Height = hub_height_m,\r\n Year = commissioning_date,\r\n Lat = latitude,\r\n Lon = longitude\r\n ) %>% \r\n arrange(Year, -Diameter) %>% \r\n mutate(\r\n Year = as.integer(str_match(Year, \"^\\\\d{4}\")[,1])\r\n )\r\n\r\n\r\n\r\nne_map <- rnaturalearth::ne_countries(scale='medium', returnclass = 'sf')\r\n\r\nturbine_anim <- wind_turbine %>% \r\n ggplot() +\r\n geom_rect(\r\n aes(xmin = -150, xmax = -50, ymin = 40, ymax = 72),\r\n fill = \"#B6D0D1\"\r\n ) +\r\n geom_sf(\r\n aes(fill = ifelse(admin == \"Canada\", \"#7BC86C\", \"#FFF8DC\")),\r\n show.legend = FALSE,\r\n data = filter(ne_map, admin %in% c(\"Canada\", \"United States of America\"))\r\n ) +\r\n scale_fill_identity() +\r\n geom_point(\r\n aes(Lon, Lat, group = ID, size = Capacity),\r\n show.legend = FALSE, alpha = 0.5, color = \"#3C59FF\"\r\n ) +\r\n geom_text(\r\n aes(x = -138, y = 43, label = as.character(Year)),\r\n size = 24, color = \"grey35\", family = \"Roboto Slab\"\r\n ) +\r\n geom_rect(\r\n aes(xmin = -150, xmax = -50, ymin = 40, ymax = 72),\r\n fill = \"transparent\", color = \"black\"\r\n ) +\r\n coord_sf(\r\n xlim = c(-150, -50),\r\n ylim = c(40, 72),\r\n expand = FALSE,\r\n clip = \"on\"\r\n ) +\r\n ggtitle(\"Canadian Wind Turbines\") +\r\n theme_void() +\r\n theme(\r\n plot.title = element_text(family = \"Adelle\", s),\r\n plot.margin = margin(1, 1, 1, 1, \"cm\")\r\n ) +\r\n transition_reveal(Year)\r\n\r\nanimate(turbine_anim, width = 1000, height = 600, nframes = 100)\r\n\r\n\r\n\r\ncapacity_data <- wind_turbine %>% \r\n group_by(Year) %>% \r\n summarize(\r\n Capacity = sum(Capacity),\r\n .groups = 'drop'\r\n ) %>% \r\n mutate(\r\n Capacity = accumulate(Capacity, sum),\r\n width = (Capacity/max(Capacity)) * 70\r\n )\r\n\r\ncapacity_anim <- capacity_data %>% \r\n ggplot(aes(x = 1, y = Capacity)) +\r\n geom_col(\r\n fill = \"#3C59FF\",\r\n ) +\r\n geom_text(\r\n aes(label = paste(as.character(round(Capacity * 0.001)), \"GW\")),\r\n hjust = -.2,\r\n family = \"IBM Plex Mono\"\r\n ) +\r\n scale_y_continuous(expand = expansion(c(.1, .4))) +\r\n coord_flip() +\r\n theme_void() +\r\n transition_states(Year)\r\n\r\nanimate(capacity_anim, res = 300, width = 1000, height = 100, nframes = 100)\r\n\r\n\r\nlibrary(magick)\r\n\r\nmap_gif <- image_read(\"turbine_map.gif\")\r\nbar_gif <- image_read(\"capacity_bar.gif\")\r\n\r\nnew_gif <- image_append(c(map_gif[1], bar_gif[1]), stack = TRUE)\r\n\r\nfor(i in 2:100){\r\n combined <- image_append(c(map_gif[i], bar_gif[i]), stack = TRUE)\r\n new_gif <- c(new_gif, combined)\r\n}\r\n\r\nnew_gif\r\n\r\n\r\n\r\n\r\nIf I don’t count all the convenient US-centric data/packages I’ve used to plot American maps before, this would be the first map I’ve made from scratch.↩︎\r\n", + "preview": "posts/2020-10-28-tidytuesday-2020-week-44/preview.png", + "last_modified": "2020-11-04T17:45:58-05:00", + "input_file": {}, + "preview_width": 735, + "preview_height": 541 + }, + { + "path": "posts/2020-10-22-analysis-of-everycolorbots-tweets/", + "title": "Analysis of @everycolorbot's tweets", + "description": "And why you should avoid neon colors", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-10-22", + "categories": [ + "data visualization", + "ggplot2", + "rtweet", + "colors" + ], + "contents": "\r\n\r\nContents\r\nIntroduction\r\nSetup\r\nAnalysis\r\nConclusion\r\n\r\nIntroduction\r\n\r\n\r\n.column {\r\n float: left;\r\n width: 50%;\r\n}\r\n\r\n.row:after {\r\n content: \"\";\r\n display: table;\r\n clear: both;\r\n}\r\n\r\n.sc {\r\n font-variant: small-caps;\r\n letter-spacing: 0.1em;\r\n}\r\n\r\nI, along with nearly two-hundred thousand other people, follow @everycolorbot on twitter. @everycolorbot is a twitter bot that tweets an image of a random color every hour (more details on github). It’s 70% a source of inspiration for new color schemes, and 30% a comforting source of constant in my otherwise hectic life.\r\nWhat I’ve been noticing about @everycolorbot’s tweets is that bright, highly saturated neon colors (yellow~green) tend to get less likes compared to cool blue colors and warm pastel colors. You can get a feel of this difference in the number of likes between the two tweets below, tweeted an hour apart:\r\n\r\n\r\n\r\n\r\n0x54e14b pic.twitter.com/Aw0cwm7uy8\r\n\r\n— Every Color (@everycolorbot) October 15, 2020\r\n\r\n\r\n\r\n\r\n\r\n0xaa70a5 pic.twitter.com/NMBF3mffS4\r\n\r\n— Every Color (@everycolorbot) October 15, 2020\r\n\r\n\r\n\r\nThis is actually not a big surprise. Bright pure colors are very harsh and straining to the eye, especially on a white background.1 For this reason bright colors are almost never used in professional web design, and are also discouraged in data visualization.\r\nSo here’s a mini experiment testing that claim: I’ll use @everycolorbot’s tweets (more specifically, the likes on the tweets) as a proxy for likeability/readability/comfortableness/etc. It’ll be a good exercise for getting more familiar with different colors! I’m also going to try a simple descriptive analysis using the HSV color representation, which is a psychologically-motivated mental model of color that I like a lot (and am trying to get a better feel for).\r\n\r\n\r\n\r\nFigure 1: HSV cylinder\r\n\r\n\r\n\r\nSetup\r\nUsing {rtweet} requires authentication from twitter. The steps to do so are very well documented on the package website so I wouldn’t expect too much trouble setting it up if it’s your first time using it. But just for illustration, here’s what my setup looks like:\r\n\r\n\r\napi_key <- 'XXXXXXXXXXXXXXXXXXXXX'\r\napi_secret_key <- 'XXXXXXXXXXXXXXXXXXXXX'\r\naccess_token <- \"XXXXXXXXXXXXXXXXXXXXX\"\r\naccess_token_secret <- \"XXXXXXXXXXXXXXXXXXXXX\"\r\n\r\ntoken <- create_token(\r\n app = \"XXXXXXXXXXXXXXXXXXXXX\",\r\n consumer_key = api_key,\r\n consumer_secret = api_secret_key,\r\n access_token = access_token,\r\n access_secret = access_token_secret\r\n)\r\n\r\n\r\n\r\nAfter authorizing, I queried the last 10,000 tweets made by @everycolorbot. It ended up only returning about a 1/3 of that because the twitter API only allows you to go back so far in time, but that’s plenty for my purposes here.\r\n\r\n\r\n\r\n\r\n\r\ncolortweets <- rtweet::get_timeline(\"everycolorbot\", 10000)\r\n\r\ndim(colortweets)\r\n\r\n\r\n\r\n\r\n [1] 3238 90\r\n\r\nAs you see above, I also got back 90 variables (columns). I only care about the time of the tweet, the number of likes it got, and the color it tweeted, so those are what I’m going to grab. I also want to clean things up a bit for plotting, so I’m going to grab just the hour from the time and just the hex code from the text.\r\n\r\n\r\ncolortweets_df <- colortweets %>% \r\n select(created_at, text, favorite_count) %>%\r\n mutate(\r\n created_at = lubridate::hour(created_at),\r\n text = paste0(\"#\", str_extract(text, \"(?<=0x).*(?= )\"))\r\n ) %>% \r\n rename(\r\n likes = favorite_count,\r\n hour = created_at,\r\n hex = text\r\n )\r\n\r\n\r\n\r\nAnd here’s what we end up with:\r\n\r\n\r\nlikes\r\n\r\n\r\nhour\r\n\r\n\r\nhex\r\n\r\n\r\n36\r\n\r\n\r\n15\r\n\r\n\r\n#65f84e\r\n\r\n\r\n65\r\n\r\n\r\n14\r\n\r\n\r\n#32fc27\r\n\r\n\r\n89\r\n\r\n\r\n13\r\n\r\n\r\n#997e13\r\n\r\n\r\n140\r\n\r\n\r\n12\r\n\r\n\r\n#ccbf09\r\n\r\n\r\n303\r\n\r\n\r\n11\r\n\r\n\r\n#665f84\r\n\r\n\r\n75\r\n\r\n\r\n10\r\n\r\n\r\n#b32fc2\r\n\r\n\r\nHere is the link to this data if you’d like to replicate or extend this analysis yourself.\r\nAnalysis\r\nBelow is a bar plot of colors where the height corresponds to the number of likes. It looks cooler than your usual bar plot because I transformed the x dimension into polar coordinates. My intent in doing this was to control for the hour of day in my analysis and visualize it like a clock (turned out better than expected!)\r\n\r\n\r\ncolortweets_df %>% \r\n arrange(-likes) %>% \r\n ggplot(aes(hour, likes, color = hex)) +\r\n geom_col(\r\n aes(size = likes),\r\n position = \"dodge\",\r\n show.legend = FALSE\r\n ) +\r\n scale_color_identity() +\r\n theme_void() +\r\n theme(\r\n plot.background = element_rect(fill = \"#222222\", color = NA),\r\n ) +\r\n coord_polar()\r\n\r\n\r\n\r\n\r\nCheck out my use of arrange() here: it’s how I tell ggplot to plot the longer bars first then the smaller bars, minimizing the overlap!\r\n\r\n\r\n\r\nI notice at least two interesting contrasts in this visualization:\r\nNeon colors (yellow, green, pink) and dark brown and black seems to dominate the center (least liked colors) while warm red~blue pastel colors dominate around the edges (most liked colors)\r\nThere also seems to be a distinction between pure blue and red in the inner-middle circle vs. the green~blue pastel colors in the outer-middle circle.\r\nSo maybe we can say that there are four clusters here:\r\nLeast liked: Bright neon colors + highly saturated dark colors\r\nLesser liked: Bright pure/near-pure colors\r\nMore liked: Darker pastel RGB\r\nMost liked: Lighter pastel mixed colors\r\nNow’s let’s try to quantitatively describe each cluster.\r\nFirst, as a sanity check, I’m just gonna eyeball the range of likes for each cluster using an un-transformed version of the above plot with units. I think we can roughly divide up the clusters at 100 likes, 200 likes, and 400 likes.\r\n\r\n\r\ncolortweets_df %>% \r\n arrange(-likes) %>% \r\n ggplot(aes(hour, likes, color = hex)) +\r\n geom_col(\r\n aes(size = likes),\r\n position = \"dodge\",\r\n show.legend = FALSE\r\n ) +\r\n geom_hline(\r\n yintercept = c(100, 200, 400), \r\n color = \"white\", \r\n linetype = 2, \r\n size = 2\r\n ) +\r\n scale_y_continuous(breaks = scales::pretty_breaks(10)) +\r\n scale_color_identity() +\r\n theme_void() +\r\n theme(\r\n plot.background = element_rect(fill = \"#222222\", color = NA),\r\n axis.line.y = element_line(color = \"white\"),\r\n axis.text.y = element_text(\r\n size = 14,\r\n color = \"white\",\r\n margin = margin(l = 3, r = 3, unit = \"mm\")\r\n )\r\n )\r\n\r\n\r\n\r\n\r\nIf our initial hypothesis about the four clusters are true, we should see these clusters having distinct profiles. Here, I’m going to use the HSV representation to quantitatively test this. To convert our hex values into HSV, I use the as.hsv() function from the {chroma} package - an R wrapper for the javascript library of the same name.\r\n\r\n\r\ncolortweets_df_hsv <- colortweets_df %>% \r\n mutate(hsv = map(hex, ~as_tibble(chroma::as.hsv(.x)))) %>% \r\n unnest(hsv)\r\n\r\n\r\n\r\n\r\nActually, I used furrr::future_map() here myself because I found the hex-hsv conversion to be sorta slow.\r\nAnd now we have the HSV values (hue, saturation, value)!\r\n\r\n\r\nlikes\r\n\r\n\r\nhour\r\n\r\n\r\nhex\r\n\r\n\r\nh\r\n\r\n\r\ns\r\n\r\n\r\nv\r\n\r\n\r\n36\r\n\r\n\r\n15\r\n\r\n\r\n#65f84e\r\n\r\n\r\n111.88235\r\n\r\n\r\n0.6854839\r\n\r\n\r\n0.9725490\r\n\r\n\r\n65\r\n\r\n\r\n14\r\n\r\n\r\n#32fc27\r\n\r\n\r\n116.90141\r\n\r\n\r\n0.8452381\r\n\r\n\r\n0.9882353\r\n\r\n\r\n89\r\n\r\n\r\n13\r\n\r\n\r\n#997e13\r\n\r\n\r\n47.91045\r\n\r\n\r\n0.8758170\r\n\r\n\r\n0.6000000\r\n\r\n\r\n140\r\n\r\n\r\n12\r\n\r\n\r\n#ccbf09\r\n\r\n\r\n56.00000\r\n\r\n\r\n0.9558824\r\n\r\n\r\n0.8000000\r\n\r\n\r\n303\r\n\r\n\r\n11\r\n\r\n\r\n#665f84\r\n\r\n\r\n251.35135\r\n\r\n\r\n0.2803030\r\n\r\n\r\n0.5176471\r\n\r\n\r\n75\r\n\r\n\r\n10\r\n\r\n\r\n#b32fc2\r\n\r\n\r\n293.87755\r\n\r\n\r\n0.7577320\r\n\r\n\r\n0.7607843\r\n\r\n\r\nWhat do we get if we average across the dimensions of HSV for each cluster?\r\n\r\n\r\ncolortweets_df_hsv <- colortweets_df_hsv %>% \r\n mutate(\r\n cluster = case_when(\r\n likes < 100 ~ \"Center\",\r\n between(likes, 100, 200) ~ \"Inner-Mid\",\r\n between(likes, 201, 400) ~ \"Outer-Mid\",\r\n likes > 400 ~ \"Edge\"\r\n ),\r\n cluster = fct_reorder(cluster, likes)\r\n )\r\n\r\ncolortweets_df_hsv %>% \r\n group_by(cluster) %>% \r\n summarize(across(h:v, mean), .groups = 'drop')\r\n\r\n\r\n # A tibble: 4 x 4\r\n cluster h s v\r\n * \r\n 1 Center 121. 0.770 0.710\r\n 2 Inner-Mid 191. 0.734 0.737\r\n 3 Outer-Mid 197. 0.589 0.710\r\n 4 Edge 249. 0.304 0.832\r\n\r\nThis actually matches up pretty nicely with our initial analysis! We find a general dislike for green colors (h value close to 120) over blue colors (h value close to 240), as well as a dislike for highly saturated colors (intense, bright) over those with low saturation (which is what gives off the “pastel” look). To help make the hue values more interpretable, here’s a color wheel with angles that correspond to the hue values in HSV.2\r\n\r\n\r\n\r\nFigure 2: Hue color wheel\r\n\r\n\r\n\r\nBut we also expect to find within-cluster variation along HSV. In particular, hue is kind of uninterpretable on a scale so it probably doesn’t make a whole lot of sense to take a mean of that. So back to the drawing plotting board!\r\nSince saturation and value do make more sense on a continuous scale, let’s draw a scatterplot for each cluster with saturation on the x-axis and value on the y-axis. I’m also going to map hue to the color of each point, but since hue is abstract on its own, I’m actually just going to replace it with the hex values (i.e., the actual color).\r\n\r\n\r\ncolortweets_df_hsv %>% \r\n ggplot(aes(s, v, color = hex)) +\r\n geom_point() +\r\n scale_color_identity() +\r\n lemon::facet_rep_wrap(~cluster) +\r\n theme_void(base_size = 16, base_family = \"Montserrat Medium\") +\r\n theme(\r\n plot.margin = margin(3, 5, 5, 5, \"mm\"),\r\n strip.text = element_text(margin = margin(b = 3, unit = \"mm\")),\r\n panel.border = element_rect(color = \"black\", fill = NA),\r\n panel.background = element_rect(fill = \"grey75\", color = NA)\r\n )\r\n\r\n\r\n\r\n\r\nHere’s the mappings spelled out again:\r\nsaturation (how colorful a color is) is mapped to the X-dimension\r\nvalue (how light a color is) is mapped to the Y-dimension\r\nhex (the actual color itself) is mapped to the COLOR dimension\r\n\r\nOur plot above reinforce what we’ve found before. Colors are more likeable (literally) the more they…\r\nMove away from green: Neon-green dominates the least-liked cluster, and that’s a blatant fact. Some forest-greens survive to the lesser-liked cluster, but is practically absent in the more-liked cluster and most-liked cluster. It looks like the only way for green to be redeemable is to either mix in with blue to become cyan and turquoise, which dominates the more-liked cluster, or severly drop in saturation to join the ranks of other pastel colors in the most-liked cluster.\r\nIncrease in value and decrease in saturation: It’s clear that the top-left corner is dominated by the more-liked and the most-liked cluster. That region is, again, where pastel colors live. They’re calmer than the bright neon colors that plague the least-liked cluster, and are more liked than highly-saturated and intense colors like those in the top right of the Outer-Mid panel. So perhaps this is a lesson that being “colorful” can only get you so far.\r\nConclusion\r\nObviously, all of this should be taken with a grain of salt. We don’t know the people behind the likes - their tastes, whether they see color differently, what medium they saw the tweet through, their experiences, etc.\r\nAnd of course, we need to remind ourselves that we rarely see a color just by itself in the world. It contrasts and harmonizes with other colors in the environment in very complex ways.\r\nBut that’s what kinda makes our analysis cool - despite all these complexities, we see evidence for many things that experts working with color emphasize: avoid pure neon, mix colors, etc. This dataset also opens us up to many more types of analyses (like an actual cluster analysis) that might be worth looking into.\r\nGood stuff.\r\n\r\nDark mode ftw!↩︎\r\nWhile all color wheels look the same, they aren’t all oriented the same. When using HSV, make sure to reference the color wheel where the red is at 0, green is as 120, and blue is at 240.↩︎\r\n", + "preview": "posts/2020-10-22-analysis-of-everycolorbots-tweets/preview.png", + "last_modified": "2021-02-13T13:29:01-05:00", + "input_file": {}, + "preview_width": 2433, + "preview_height": 2259 + }, + { + "path": "posts/2020-10-13-designing-guiding-aesthetics/", + "title": "Designing guiding aesthetics", + "description": "The fine line between creativity and noise", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-10-13", + "categories": [ + "data visualization", + "ggplot2", + "tidytuesday" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nReflections on guiding aesthetics\r\nWhy bother with guiding aesthetics?\r\nDesigning guiding aesthetics\r\nMy thought process\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n\r\n\r\n\r\nReflections on guiding aesthetics\r\nAdmittedly, the plot itself is quite simple, but I learned a lot from this process. So, breaking from the usual format of my tidytuesday blogposts, I want to talk about the background and motivation behind the plot as this was a big step in a new (and exciting!) direction for me that I’d like to document.\r\nJust for clarification, I’m using the term guiding aesthetics to refer to elements of the plot that do not represent a variable in the data, but serves to emphasize the overall theme or topic of the being visualized. So the mountains in my plot do not themselves contain any data, but it’s the thing that tells readers that the plot is about mountains (a valuable, but different kind of info!). But more on that later.\r\nWhy bother with guiding aesthetics?\r\nThis was my first time adding a huge element to a plot that wasn’t meaningful, in the sense of representing the data. As someone in academia working on obscure topics (as one does in academia), I’m a firm believer in making your plots as simple and minimal as possible. So I, like many others, think that it’s always a huge risk to add elements that are not absolutely necessary.\r\nBut as you might imagine, I first fell in love with data visualization not because of how objective and straightforward they are, but because of how eye-catching they can be. Like, when I was young I used to be really into insects. In fact, I read insect encyclopedias as a hobby. That TMI is relevant because those are full of data(!) visualizations that employ literal mappings of data, since those are easy to interpret for children. For example, consider the following diagram of the life cycle of the Japanese beetle from the USDA.\r\n\r\n\r\n\r\nFigure 1: Diagram of the life cycle of the Japanese beetle\r\n\r\n\r\n\r\nAs a child, I never appreciated/realized all the data that was seamlessly packed into diagrams like this. But with my Grammar of Graphics lens on, I can now see that:\r\nThe developmental stage at each month is mapped to x\r\nThe depth at which the developing beetle lives at each stage is mapped to y\r\nThe appearance of the beetle at each developmental stage is mapped to shape\r\nThe size of the beetle at each developmental stage is mapped to, well, size\r\nBut I could have easily plotted something like this instead:\r\n\r\n\r\nbeetles <- tibble::tribble(\r\n ~Month, ~Depth, ~Stage, ~Size,\r\n \"JAN\", -10, \"Larva\", 10,\r\n \"FEB\", -8, \"Larva\", 12,\r\n \"MAR\", -7, \"Larva\", 14,\r\n \"APR\", -7, \"Larva\", 14,\r\n \"MAY\", -6, \"Pupa\", 11,\r\n \"JUN\", 0, \"Beetle\", 12,\r\n \"JUL\", 0, \"Beetle\", 12,\r\n \"AUG\", -3, \"Larva\", 1,\r\n \"SEP\", -2, \"Larva\", 2,\r\n \"OCT\", -1, \"Larva\", 4,\r\n \"NOV\", -3, \"Larva\", 5,\r\n \"DEC\", -8, \"Larva\", 7\r\n)\r\n\r\nbeetles$Month <- fct_inorder(beetles$Month)\r\n\r\nggplot(beetles, aes(x = Month, y = Depth, size = Size, shape = Stage)) +\r\n geom_point() +\r\n ggtitle(\"The lifecycle of the Japanese beetle\")\r\n\r\n\r\n\r\n\r\nBoth visuals represent the data accurately, but of course the diagram looks better. And not just because it’s complex, but also because it exploits the associations between aesthetic dimensions and their meanings, as well as the strength of those associations.\r\nFor example, the shape dimension literally corresponds to shape, and the shape of the different developmental stages of the beetle are unique enough for there to be interesting within-stage variation and still be recognizable - e.g., the beetle looks different crawling out the ground in June and entering back in August, but it’s still recognizable as a beetle (and the same beetle at that!). This would’ve been difficult if the variable being mapped to shape was something arbitrary and abstract, like the type of protein that’s most produced at a particular stage. The diagram thus exploits the strength of the association between the shape dimension and the literal shapes of the beetle to represent the developmental stages. And it should be clear now that the same goes for y and size.\r\nHow about x? There’s no such strong/literal interpretation of the x-dimension - at best it just means something horizontal. So it’s actually fitting that a similarly abstract concept like the passage of time is mapped to x. We understand time linearly, and often see time as the x-axis in other plots, so it fits pretty naturally here.\r\nLastly, let’s talk about the color dimension. Even though no information was actually mapped to color, we certainly are getting some kind of information from the colors used in the plot. Literally put, we’re getting the information that the grass is green and the soil is brown. Now, that information is actually not representing any data that we care about so it’s technically visual noise, but it helps bring forward the overall theme of the diagram. While this worked out in the end, notice now that you have effectively thrown out color as a dimension that can convey meaningful information. That was a necessary tradeoff, but a well motivated one, since the information that the diagram is trying to convey doesn’t really need color.\r\nDesigning guiding aesthetics\r\nI’m hardly the expert, but I found it helpful to think of the process as mediating the tug of war between the guiding aesthetic and the variables in the data as they fight over space in different mapping dimensions.\r\nThis meant I had to make some changes to my usual workflow for explanatory data visualization, which mostly goes something like this:\r\nTake my response variable and map it to y\r\nFigure out the distribution of my response variables and choose the geom (e.g., boxplot, histogram).\r\nMap my dependent variables to other dimensions - this usually ends at either just x or x + facet groupings\r\nBut if I’m trying to incorporate guiding aesthetics, my workflow would look more like this:\r\nStart with a couple ideas for a visual representation of the topic (scenes, objects, etc.)\r\nFigure out the dimensions that the variables in the data can be mapped to\r\nFigure out the dimensions that each visual representation would intrude in\r\nMake compromises between (2) and (3) in a way that maximizes the quality of the data and the visual representation\r\nOf course, this kind of flexibility is unique to exploratory data visualization, in particular to the kinds where none of the variable is significant or interesting a priori. Of course in real life there will be a lot more constraints, but because we can assume a great degree of naivety towards the data for #tidytuesday, I get to pick and choose what I want to plot (which makes #tidytuesday such a great place to practice baby steps)!\r\nFor illustration, here’s my actual thought process while I was making the #tidytuesday plot.\r\nWARNING: a very non-linear journey ahead!\r\nMy thought process\r\nThe topic was about Himalayan climbing expeditions, so I wanted my visual to involve a mountain shape. The most obvious idea that came to mind was to draw a mountain where the peak of that mountain corresponded with their height_metres, a variable from the peaks data. It’s straightforward and intuitive! So I drew a sketch (these are the original rough sketches - please forgive the quality!)\r\n\r\n\r\n\r\nFigure 2: The first guiding aesthetic idea\r\n\r\n\r\n\r\nBut this felt… a bit empty. I threw in Mount Everest, but now what? I still had data on hundreds of more Himalayan peaks that were in the dataset. Just visualizing Mount Everest is not badly motivated per se (it’s the most famous peak afterall), but it wouldn’t make an interesting plot since there wasn’t much data on individual peaks. I wanted to add a few more mountain shapes, but I struggled to find a handful of peaks that formed a coherent group. I knew that if I wanted to go with the idea of mountain shapes as the guiding aesthetic, I could only manage to fit about a dozen or so without it looking too crowded.\r\nI put that issue aside for the moment and moved on while trying to accommodate for the possibility that I may have to fit in many more peaks. I thought about having a single mountain shape just for Mount Everest, and a point with a vertical spikeline for all other peaks to emphasize the y-axis representing height_metres.\r\n\r\n\r\n\r\nFigure 3: The second guiding aesthetic idea\r\n\r\n\r\n\r\nAt this point I started thinking about the x-axis. If I do use points to represent peaks (specifically, peak height), where would I actually position each point? Just randomly along the x-axis? It really started hitting me at this point that the quality of my data was pretty abysmal. Even if I ended up with a pretty visualization, I didn’t think I could justify calling it a data visualization. I felt that it’d be a reach to use complex visuals just to communicate a single variable.\r\nI toyed around with enriching the data being plotted. What if I use size of the dots to represent the average age of climbers who reached the peak, from the memmbers data? Or what if I used shape of country flags on top of the dots to represent the country that first reached the peak, from the expeditions data?\r\nThese were all cool ideas, but I kept coming back to the need to make the x-dimension meaningful. It just stood out too much. I didn’t think I could prevent the reader from expecting some sort of a meaning from the positioning of the dots along the x-axis.\r\nSo I went back to Step #2. I gathered up all the continuous variables across the three data in the #tidytuesday dataset (peaks, members, expeditions) and evaluated how good of a candidate each of them were for being mapped to x. This was the most time-consuming part of the process, and I narrowed it down to three candidates:\r\nexpeditions$members: looked okay at first, but once I started aggregating (averaging) by peak, the distribution became quite narrow. That made it less interesting and not very ideal for mountain shapes (the typical mountain shape is wider than they are tall).\r\nmembers$age: has a nice distribution and a manageable range with no extreme outliers.\r\npeaks$first_ascent_year: also has the above features + doesn’t need to be aggregated in some way, so the x-axis would have a very straight forward interpretation.\r\nThe first_ascent_year variable looked the most promising, so that’s what I pursued (and ended up ultimately adopting!).\r\n\r\n\r\n\r\nFigure 4: The third guiding aesthetic idea\r\n\r\n\r\n\r\nNow I felt like I had more direction to tackle the very first issue that I ran into during this process: the problem of picking out a small set of peaks that were interesting and well-motivated. I played around more with several options, but I ultimately settled on something very simple - the top 10 most popular peaks. Sure it’s overused and not particularly exciting, but that was a sacrifice that my over-worked brain was willing to make at the time.\r\nAnd actually, it turned out to be a great fit with my new x variable! It turns out that the top 10 most climbed peaks are also those that were among the first to be climbed (a correlation that sorta makes sense), so this set of peaks had an additional benefit of localizing the range of x to between the 1940s-1960s. And because 10 was a manageable number, I went ahead with my very first idea of having a mountain accompanying each point, where the peaks represent the peak of the guiding aesthetic (the mountain shape) as well as the height_metres and first_ascent_year.\r\nFinally, it came time for me to polish up on the mountains. I needed to decide on features of the mountains like how wide the base is, how many valleys and peaks it has, how tall the peaks are relative to each other, etc. I had to be careful that these superfluous features do not encroach on the dimensions where I mapped my data to - the x and y. Here, I had concerns about two of the mountain features in particular: base width and smaller peaks:\r\nThe base width was troubling because how wide the base of the mountain stretches could be interpreted as representing another variable that has to do with year (like the first and last time it was climbed, for example). This was a bit difficult to deal with, but I settled on a solution which was to keep the base width constant. By not having that feature vary at all, I could suppress any expectation for it to carry some sort of meaning. It’s kind of like how when you make a scatterplot with variables mapped to x and y, you don’t imbue any special meaning to the fact that the observations are represented by a circle (point), beacuse all of them are that shape. If they varied in any way, say you also have some rectangles and triangles, then you’d start expecting the shape to represent something meaningful.\r\nThe smaller peaks of the mountain shapes were troubling because I was already using the peak to represent the height. It helped that the actual peaks representing the data were also marked by a point and a label of the peak name. But to make it extra clear that the they were pure noise, I decided to randomly generate peaks and valleys, and tried to make that obvious. In the code attached at the bottom of this post, several parameters of the mountain-generating function allowed me to do this. It also helped that I added a note saying that the mountains were randomly generated when I tweeted it, which is kind of cheating perhaps, but it worked!\r\n\r\n\r\nI've been feeling particularly inspired by this week's #TidyTuesday so I made another plot! This is a simple scatterplot of peak height by year of first ascent, but with a twist: each point is also represented by the peak of a randomly generated mountain! #rstats pic.twitter.com/CqNQjdMYXP\r\n\r\n— June (@yjunechoe) September 25, 2020\r\n\r\nThat wraps up my long rant on how I made my mountains plot! For more context, making the plot took about a half a day worth of work, which isn’t too bad for a first attempt! Definitely looking forward to getting more inspirations like this in the future.\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\n\r\nmake_mountain <- function(x_start, x_end, base = 0, peak_x, peak_y, n_peaks = 3, peaks_ratio = 0.3, side.first = \"left\") {\r\n \r\n midpoint_abs <- (peak_y - base)/2 + base\r\n midpoint_rel <- (peak_y - base)/2\r\n \r\n side_1_n_peaks <- floor(n_peaks/2)\r\n side_2_n_peaks <- n_peaks - side_1_n_peaks -1\r\n \r\n side_1_x <- seq(x_start, peak_x, length.out = side_1_n_peaks * 2 + 2)\r\n side_1_x <- side_1_x[-c(1, length(side_1_x))]\r\n \r\n side_2_x <- seq(peak_x, x_end, length.out = side_2_n_peaks * 2 + 2)\r\n side_2_x <- side_2_x[-c(1, length(side_2_x))]\r\n \r\n side_1_y <- numeric(length(side_1_x))\r\n side_1_y[c(TRUE, FALSE)] <- runif(length(side_1_y)/2, midpoint_abs, midpoint_abs + midpoint_rel * peaks_ratio)\r\n side_1_y[c(FALSE, TRUE)] <- runif(length(side_1_y)/2, midpoint_abs - midpoint_rel * peaks_ratio, midpoint_abs)\r\n \r\n side_2_y <- numeric(length(side_2_x))\r\n side_2_y[c(TRUE, FALSE)] <- runif(length(side_2_y)/2, midpoint_abs, midpoint_abs + midpoint_rel * peaks_ratio)\r\n side_2_y[c(FALSE, TRUE)] <- runif(length(side_2_y)/2, midpoint_abs - midpoint_rel * peaks_ratio, midpoint_abs)\r\n \r\n if (side.first == \"left\") {\r\n side_left <- data.frame(x = side_1_x, y = side_1_y)\r\n side_right <- data.frame(x = side_2_x, y = rev(side_2_y))\r\n } else if (side.first == \"right\") {\r\n side_left <- data.frame(x = side_2_x, y = side_2_y)\r\n side_right <- data.frame(x = side_1_x, y = rev(side_1_y))\r\n } else {\r\n error('Inavlid value for side.first - choose between \"left\" (default) or \"right\"')\r\n }\r\n \r\n polygon_points <- rbind(\r\n data.frame(x = c(x_start, peak_x, x_end), y = c(base, peak_y, base)),\r\n side_left,\r\n side_right\r\n )\r\n \r\n polygon_points[order(polygon_points$x),]\r\n\r\n}\r\n\r\ntuesdata <- tidytuesdayR::tt_load(\"2020-09-22\")\r\n\r\npeaks <- tuesdata$peaks\r\nexpeditions <- tuesdata$expeditions\r\n\r\ntop_peaks <- expeditions %>% \r\n count(peak_name) %>% \r\n slice_max(n, n = 10)\r\n\r\nplot_df <- peaks %>% \r\n filter(peak_name %in% top_peaks$peak_name) %>% \r\n arrange(-height_metres) %>% \r\n mutate(peak_name = fct_inorder(peak_name))\r\n\r\nplot_df %>% \r\n ggplot(aes(x = first_ascent_year, y = height_metres)) +\r\n pmap(list(plot_df$first_ascent_year, plot_df$height_metres, plot_df$peak_name),\r\n ~ geom_polygon(aes(x, y, fill = ..3), alpha = .6,\r\n make_mountain(x_start = 1945, x_end = 1965, base = 5000,\r\n peak_x = ..1, peak_y = ..2, n_peaks = sample(3:5, 1)))\r\n ) +\r\n geom_point(color = \"white\") +\r\n ggrepel::geom_text_repel(aes(label = peak_name),\r\n nudge_y = 100, segment.color = 'white',\r\n family = \"Montserrat\", fontface = \"bold\", color = \"white\") +\r\n guides(fill = guide_none()) +\r\n scale_x_continuous(expand = expansion(0.01, 0)) +\r\n scale_y_continuous(limits = c(5000, 9000), expand = expansion(0.02, 0)) +\r\n theme_minimal(base_family = \"Montserrat\", base_size = 12) +\r\n labs(title = \"TOP 10 Most Attempted Himalayan Peaks\",\r\n x = \"First Ascent Year\", y = \"Peak Height (m)\") +\r\n palettetown::scale_fill_poke(pokemon = \"articuno\") +\r\n theme(\r\n plot.title.position = \"plot\",\r\n plot.title = element_text(size = 24, vjust = 3, family = \"Lora\"),\r\n text = element_text(color = \"white\", face = \"bold\"),\r\n axis.text = element_text(color = \"white\"),\r\n axis.title = element_text(size = 14),\r\n axis.title.x = element_text(vjust = -2),\r\n axis.title.y = element_text(vjust = 4),\r\n plot.margin = margin(1, .5, .7, .7, \"cm\"),\r\n plot.background = element_rect(fill = \"#5C606A\", color = NA),\r\n panel.grid = element_blank(),\r\n )\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-10-13-designing-guiding-aesthetics/preview.png", + "last_modified": "2021-06-11T03:43:20-04:00", + "input_file": {}, + "preview_width": 8503, + "preview_height": 6377 + }, + { + "path": "posts/2020-09-26-demystifying-stat-layers-ggplot2/", + "title": "Demystifying stat_ layers in {ggplot2}", + "description": "The motivation behind stat, the distinction between stat and geom, and a case study of stat_summary()", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-27", + "categories": [ + "data visualization", + "ggplot2", + "tutorial" + ], + "contents": "\r\n\r\nContents\r\nIntroduction\r\nWhen and why should I use STAT?\r\nInterim Summary #1\r\n\r\nUnderstanding STAT with stat_summary()\r\nInterim Summary #2\r\n\r\nPutting STAT to use\r\n1. Error bars showing 95% confidence interval\r\n2. A color-coded bar plot of medians\r\n3. Pointrange plot with changing size\r\n\r\nConclusion\r\nMain Ideas\r\nSTAT vs. GEOM or STAT and GEOM?\r\n\r\n\r\n\r\n\r\n\r\nUPDATE 10/5/20: This blog post was featured in the rweekly highlights podcast! Thanks to the rweekly team for a flattering review of my tutorial!\r\nIntroduction\r\n(Feel free to skip the intro section if you want to get to the point!)\r\nA powerful concept in the Grammar of Graphics is that variables are mapped onto aesthetics. In {ggplot2}, a class of objects called geom implements this idea. For example, geom_point(mapping = aes(x = mass, y = height)) would give you a plot of points (i.e. a scatter plot), where the x-axis represents the mass variable and the y axis represents the height variable.\r\nBecause geom_*()s1 are so powerful and because aesthetic mappings are easily understandable at an abstract level, you rarely have to think about what happens to the data you feed it. Take this simple histogram for example:\r\n\r\n\r\ndata(\"penguins\", package = \"palmerpenguins\")\r\n\r\nggplot(data = penguins, mapping = aes(x = body_mass_g)) +\r\n geom_histogram()\r\n\r\n\r\n\r\n\r\nWhat’s going on here? You might say that the body_mass_g variable is represented in the x-axis. Sure, that’s not wrong. But a fuller explanation would require you to talk about these extra steps under the hood:\r\nThe variable mapped to x is divided into discrete bins\r\nA count of observations within each bin is calculated\r\nThat new variable is then represented in the y axis\r\nFinally, the provided x variable and the internally calculated y variable is represented by bars that have certain position and height\r\nI don’t mean to say here that you are a total fool if you can’t give a paragraph-long explanation of geom_histogram(). Rather, my intention here is to emphasize that the data-to-aesthetic mapping in GEOM objects is not neutral, although it can often feel very natural, intuitive, and objective (and you should thank the devs for that!). Just think about the many ways in which you can change any of the internal steps above, especially steps 12 and 23, while still having the output look like a histogram.\r\nThis important point rarely crosses our mind, in part because of what we have gotten drilled into our heads when we first started learning ggplot. As beginners we’ve likely experienced the frustration of having all the data we need to plot something, but ggplot just won’t work. You could imagine a beginner today who’s getting frustrated because geom_point(aes(x = mass, y = height)) throws an error with the following data.\r\n\r\n # A tibble: 2 x 4\r\n variable subject1 subject2 subject3\r\n \r\n 1 mass 75 70 55\r\n 2 height 154 172 144\r\n\r\nAnd what would StackOverflow you tell this beginner? You’d probably tell them to put the data in a tidy format4 first.\r\n\r\n # A tibble: 3 x 3\r\n subject mass height\r\n \r\n 1 1 75 154\r\n 2 2 70 172\r\n 3 3 55 144\r\n\r\nNow, that’s something you can tell a beginner for a quick and easy fix. But if you still simply think “the thing that makes ggplot work = tidy data”, it’s important that you unlearn this mantra in order to fully understand the motivation behind stat.\r\nWhen and why should I use STAT?\r\nYou could be using ggplot every day and never even touch any of the two-dozen native stat_*() functions. In fact, because you’ve only used geom_*()s, you may find stat_*()s to be the esoteric and mysterious remnants of the past that only the developers continue to use to maintain law and order in the depths of source code hell.\r\nIf that describes you, you might wonder why you even need to know about all these stat_*() functions.\r\n\r\n\r\n\r\nWell, the main motivation for stat is simply this:\r\n\r\n“Even though the data is tidy it may not represent the values you want to display”5\r\n\r\nThe histogram discussion in the previous section was a good example to this point, but here I’ll introduce another example that I think will hit the point home.\r\nSuppose you have a data simple_data that looks like this:\r\n\r\n\r\nsimple_data <- tibble(group = factor(rep(c(\"A\", \"B\"), each = 15)),\r\n subject = 1:30,\r\n score = c(rnorm(15, 40, 20), rnorm(15, 60, 10)))\r\n\r\n\r\n\r\n\r\n\r\n\r\n{\"columns\":[{\"label\":[\"group\"],\"name\":[1],\"type\":[\"fct\"],\"align\":[\"left\"]},{\"label\":[\"subject\"],\"name\":[2],\"type\":[\"int\"],\"align\":[\"right\"]},{\"label\":[\"score\"],\"name\":[3],\"type\":[\"dbl\"],\"align\":[\"right\"]}],\"data\":[{\"1\":\"A\",\"2\":\"1\",\"3\":\"28.79\"},{\"1\":\"A\",\"2\":\"2\",\"3\":\"35.40\"},{\"1\":\"A\",\"2\":\"3\",\"3\":\"71.17\"},{\"1\":\"A\",\"2\":\"4\",\"3\":\"41.41\"},{\"1\":\"A\",\"2\":\"5\",\"3\":\"42.59\"},{\"1\":\"A\",\"2\":\"6\",\"3\":\"74.30\"},{\"1\":\"A\",\"2\":\"7\",\"3\":\"49.22\"},{\"1\":\"A\",\"2\":\"8\",\"3\":\"14.70\"},{\"1\":\"A\",\"2\":\"9\",\"3\":\"26.26\"},{\"1\":\"A\",\"2\":\"10\",\"3\":\"31.09\"},{\"1\":\"A\",\"2\":\"11\",\"3\":\"64.48\"},{\"1\":\"A\",\"2\":\"12\",\"3\":\"47.20\"},{\"1\":\"A\",\"2\":\"13\",\"3\":\"48.02\"},{\"1\":\"A\",\"2\":\"14\",\"3\":\"42.21\"},{\"1\":\"A\",\"2\":\"15\",\"3\":\"28.88\"},{\"1\":\"B\",\"2\":\"16\",\"3\":\"77.87\"},{\"1\":\"B\",\"2\":\"17\",\"3\":\"64.98\"},{\"1\":\"B\",\"2\":\"18\",\"3\":\"40.33\"},{\"1\":\"B\",\"2\":\"19\",\"3\":\"67.01\"},{\"1\":\"B\",\"2\":\"20\",\"3\":\"55.27\"},{\"1\":\"B\",\"2\":\"21\",\"3\":\"49.32\"},{\"1\":\"B\",\"2\":\"22\",\"3\":\"57.82\"},{\"1\":\"B\",\"2\":\"23\",\"3\":\"49.74\"},{\"1\":\"B\",\"2\":\"24\",\"3\":\"52.71\"},{\"1\":\"B\",\"2\":\"25\",\"3\":\"53.75\"},{\"1\":\"B\",\"2\":\"26\",\"3\":\"43.13\"},{\"1\":\"B\",\"2\":\"27\",\"3\":\"68.38\"},{\"1\":\"B\",\"2\":\"28\",\"3\":\"61.53\"},{\"1\":\"B\",\"2\":\"29\",\"3\":\"48.62\"},{\"1\":\"B\",\"2\":\"30\",\"3\":\"72.54\"}],\"options\":{\"columns\":{\"min\":{},\"max\":[10]},\"rows\":{\"min\":[10],\"max\":[10]},\"pages\":{}}}\r\n \r\n\r\nAnd suppose that you want to draw a bar plot where each bar represents group and the height of the bars corresponds to the mean of score for each group.\r\nIf you’re stuck in the mindset of “the data that I feed in to ggplot() is exactly what gets mapped, so I need to tidy it first and make sure it contains all the aesthetics that each geom needs”, you would need to transform the data before piping it in like this:\r\n\r\n\r\nsimple_data %>%\r\n group_by(group) %>% \r\n summarize(\r\n mean_score = mean(score),\r\n .groups = 'drop' # Remember to ungroup!\r\n ) %>% \r\n ggplot(aes(x = group, y = mean_score)) +\r\n geom_col()\r\n\r\n\r\n\r\n\r\nIt’s a good practice to always ungroup your dataframe before passing into ggplot, as having grouped data can lead to unintended behaviors that are hard to debug.\r\n\r\n\r\n\r\nWhere the data passed in looks like this:\r\n\r\n # A tibble: 2 x 2\r\n group mean_score\r\n \r\n 1 A 43.0\r\n 2 B 57.5\r\n\r\nOk, not really a problem there. But what if we want to add in error bars too? Error bars also plot a summary statistic (the standard error), so we’d need make another summary of the data to pipe into ggplot().\r\nLet’s first plot the error bar by itself, we’re again passing in a transformed data\r\n\r\n\r\nsimple_data %>% \r\n group_by(group) %>% \r\n summarize(\r\n mean_score = mean(score),\r\n se = sqrt(var(score)/length(score)),\r\n .groups = 'drop'\r\n ) %>% \r\n mutate(\r\n lower = mean_score - se,\r\n upper = mean_score + se\r\n ) %>% \r\n ggplot(aes(x = group, y = mean_score, ymin = lower, ymax = upper)) +\r\n geom_errorbar()\r\n\r\n\r\n\r\n\r\nWhere the transformed data looks like this:\r\n\r\n # A tibble: 2 x 5\r\n group mean_score se lower upper\r\n \r\n 1 A 43.0 4.37 38.7 47.4\r\n 2 B 57.5 2.82 54.7 60.4\r\n\r\nOk, now let’s try combining the two. One way to do this is to save the data paseed in for the bar plot and the data passed in for the errorbar plot as two separate variables, and then call each in their respective geoms:\r\n\r\n\r\nsimple_data_bar <- simple_data %>%\r\n group_by(group) %>% \r\n summarize(\r\n mean_score = mean(score),\r\n .groups = 'drop'\r\n )\r\n \r\nsimple_data_errorbar <- simple_data %>% \r\n group_by(group) %>% \r\n summarize(\r\n mean_score = mean(score),\r\n se = sqrt(var(score)/length(score)),\r\n .groups = 'drop'\r\n ) %>% \r\n mutate(\r\n lower = mean_score - se,\r\n upper = mean_score + se\r\n )\r\n\r\nggplot() +\r\n geom_col(\r\n aes(x = group, y = mean_score),\r\n data = simple_data_bar\r\n ) +\r\n geom_errorbar(\r\n aes(x = group, y = mean_score, ymin = lower, ymax = upper),\r\n data = simple_data_errorbar\r\n )\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nYeah… that code is a mouthful. The above approach is not parsimonious because we keep repeating similar processes in different places.6 If you, like myself, don’t like how this looks, then let this be a lesson that this is the consequence of thinking that you must always prepare a tidy data containing values that can be DIRECTLY mapped to geometric objects.\r\nAnd on a more theoretical note, simple_data_bar and simple_data_errorbar aren’t even really “tidy” in the original sense of the term. We need to remind ourselves here that tidy data is about the organization of observations in the data. Under this definition, values like bar height and the top and bottom of whiskers are hardly observations themselves. Rather, they’re abstractions or summaries of the actual observations in our data simple_data which, if you notice, we didn’t even use to make our final plot above!\r\n\r\n\r\n\r\nFigure 1: Tidy data is about the organization of observations.\r\n\r\n\r\n\r\nSo not only is it inefficient to create a transformed dataframe that suits the needs of each geom, this method isn’t even championing the principles of tidy data like we thought.7\r\nWhat we should do instead is to take advantage of the fact that our original data simple_data is the common denominator of simple_data_bar and simple_data_errorbar!\r\nWouldn’t it be nice if you could just pass in the original data containing all observations (simple_data) and have each layer internally transform the data in appropriate ways to suit the needs of the geom for that layer?\r\nOh, so you mean something like this?\r\n\r\n\r\nsimple_data %>% \r\n ggplot(aes(group, score)) +\r\n stat_summary(geom = \"bar\") +\r\n stat_summary(geom = \"errorbar\")\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nInterim Summary #1\r\nIn this section, I built up a tedious walkthrough of making a barplot with error bars using only geom_*()s just to show that two lines of stat_summary() with a single argument can achieve the same without even touching the data through any form of pre-processing.\r\nSo that was a taste of how powerful stat_*()s can be, but how do they work and how can you use them in practice?\r\nUnderstanding STAT with stat_summary()\r\nLet’s analyze stat_summary() as a case study to understand how stat_*()s work more generally. I think that stat_summary() is a good choice because it’s a more primitive version of many other stat_*()s and is likely to be the one that you’d end up using the most for visualizations in data science.\r\nBefore we start, let’s create a toy data to work with. Let’s call this data height_df because it contains data about a group and the height of individuals in that group.\r\n\r\n\r\nheight_df <- tibble(group = \"A\",\r\n height = rnorm(30, 170, 10))\r\n\r\n\r\n\r\n\r\n\r\n\r\n{\"columns\":[{\"label\":[\"group\"],\"name\":[1],\"type\":[\"chr\"],\"align\":[\"left\"]},{\"label\":[\"height\"],\"name\":[2],\"type\":[\"dbl\"],\"align\":[\"right\"]}],\"data\":[{\"1\":\"A\",\"2\":\"174.3\"},{\"1\":\"A\",\"2\":\"167.0\"},{\"1\":\"A\",\"2\":\"179.0\"},{\"1\":\"A\",\"2\":\"178.8\"},{\"1\":\"A\",\"2\":\"178.2\"},{\"1\":\"A\",\"2\":\"176.9\"},{\"1\":\"A\",\"2\":\"175.5\"},{\"1\":\"A\",\"2\":\"169.4\"},{\"1\":\"A\",\"2\":\"166.9\"},{\"1\":\"A\",\"2\":\"166.2\"},{\"1\":\"A\",\"2\":\"163.1\"},{\"1\":\"A\",\"2\":\"167.9\"},{\"1\":\"A\",\"2\":\"157.3\"},{\"1\":\"A\",\"2\":\"191.7\"},{\"1\":\"A\",\"2\":\"182.1\"},{\"1\":\"A\",\"2\":\"158.8\"},{\"1\":\"A\",\"2\":\"166.0\"},{\"1\":\"A\",\"2\":\"165.3\"},{\"1\":\"A\",\"2\":\"177.8\"},{\"1\":\"A\",\"2\":\"169.2\"},{\"1\":\"A\",\"2\":\"172.5\"},{\"1\":\"A\",\"2\":\"169.7\"},{\"1\":\"A\",\"2\":\"169.6\"},{\"1\":\"A\",\"2\":\"183.7\"},{\"1\":\"A\",\"2\":\"167.7\"},{\"1\":\"A\",\"2\":\"185.2\"},{\"1\":\"A\",\"2\":\"154.5\"},{\"1\":\"A\",\"2\":\"175.8\"},{\"1\":\"A\",\"2\":\"171.2\"},{\"1\":\"A\",\"2\":\"172.2\"}],\"options\":{\"columns\":{\"min\":{},\"max\":[10]},\"rows\":{\"min\":[10],\"max\":[10]},\"pages\":{}}}\r\n \r\n\r\nWe can visualize the data with a familiar geom, say geom_point():\r\n\r\n\r\nheight_df %>% \r\n ggplot(aes(x = group, y = height)) +\r\n geom_point()\r\n\r\n\r\n\r\n\r\nAs a first step in our investigation, let’s just replace our familiar geom_point() with the scary-looking stat_summary() and see what happens:\r\n\r\n\r\nheight_df %>% \r\n ggplot(aes(x = group, y = height)) +\r\n stat_summary()\r\n\r\n\r\n\r\n\r\nInstead of points, we now see a point and a line through that point. And before you get confused, this is actually one geom, called pointrange, not two separate geoms.8 Now that that’s cleared up, we might ask: what data is being represented by the pointrange?\r\nAnswering this question requires us to zoom out a little bit and ask: what variables does pointrange map as a geom? By looking at the documentation with ?geom_pointrange we can see that geom_pointrange() requires the following aesthetics:\r\nx or y\r\nymin or xmin\r\nymax or xmax\r\nSo now let’s look back at our arguments in aes(). We said that group is mapped to x and that height is mapped to y. But we never said anything about ymin/xmin or ymax/xmax anywhere. So how is stat_summary() drawing a pointrange if we didn’t give it the required aesthetic mappings?\r\nWell, a good guess is that stat_summary() is transforming the data to calculate the necessary values to be mapped to pointrange. Here’s one reason for that guess - I’ve been suppressing message throughout this post but if you run the above code with stat_summary() yourself, you’d actually get this message:\r\n\r\n No summary function supplied, defaulting to `mean_se()`\r\n\r\nHuh, a summary function? That sounds promising. Maybe that’s the key to our mystery!\r\nFirst, we see from the documentation of stat_summary() that this mean_se() thing is the default value for the fun.data argument (we’ll talk more on this later).\r\nNext, let’s call it in the console to see what it is:\r\n\r\n\r\nmean_se\r\n\r\n\r\n function (x, mult = 1) \r\n {\r\n x <- stats::na.omit(x)\r\n se <- mult * sqrt(stats::var(x)/length(x))\r\n mean <- mean(x)\r\n new_data_frame(list(y = mean, ymin = mean - se, ymax = mean + \r\n se), n = 1)\r\n }\r\n \r\n \r\n\r\nOk, so it’s a function that takes some argument x and a second argument mult with the default value 1.\r\nLet’s go over what it does by breaking down the function body line by line:\r\nRemove NA values\r\nCalculate variable se which is the standard error of the values in x using the equation \\(SE = \\sqrt{\\frac{1}{N}\\sum_{i=1}^N(x_i-\\bar{x})^2}\\)\r\nCalculate the variable mean9 which is the mean of x\r\nCreate a new dataframe with one row, with columns y, ymin, and ymax, where y is the mean of x, ymin is one standard error below the mean, and ymax is one standard error above the mean.10\r\nA cool thing about this is that although mean_se() seems to be exclusively used for internal operations, it’s actually available in the global environment from loading {ggplot2}. So let’s pass height_df to mean_se() and see what we get back!\r\n\r\n\r\nmean_se(height_df)\r\n\r\n\r\n Error: Elements must equal the number of rows or 1\r\n\r\n\r\n\r\n\r\nUhhh what?\r\nDo you see what happened just now? This is actually really important: stat_summary() summarizes one dimension of the data.11 mean_se() threw an error when we passed it our whole data because it was expecting just a vector of the variable to be summarized.\r\n\r\nWhenever you’re trying out a new stat_*() function, make sure to check what variables/object types the statistical transformation is being applied to!\r\nOk now that we’ve went over that little mishap, let’s give mean_se() the vector it wants.\r\n\r\n\r\nmean_se(height_df$height)\r\n\r\n\r\n y ymin ymax\r\n 1 171.8 170.3 173.3\r\n\r\nAnd look at that, these look like they’re the same values that were being represented by the mid-point and the end-points of the pointrange plot that we drew with stat_summary() above!\r\nYou know how else we can check that this is the case? With this neat function called layer_data().\r\nWe can pull the data that was used to draw the pointrange by passing our plot object to layer_data() and setting the second argument to 112:\r\n\r\n\r\npointrange_plot <- height_df %>% \r\n ggplot(aes(x = group, y = height)) +\r\n stat_summary()\r\n\r\nlayer_data(pointrange_plot, 1)\r\n\r\n\r\n x group y ymin ymax PANEL flipped_aes colour size linetype shape fill\r\n 1 1 1 171.8 170.3 173.3 1 FALSE black 0.5 1 19 NA\r\n alpha stroke\r\n 1 NA 1\r\n\r\nWould ya look at that! There’s a lot of stuff in there, but it looks like the values for y, ymin, and ymax used for the actual plot match up with the values we calculated with mean_se() above!\r\nWe’ve solved our mystery of how the pointrange was drawn when we didn’t provide all the required mappings!\r\n\r\n\r\n\r\nInterim Summary #2\r\nTo summarize this section (ha!), stat_summary() works in the following order:\r\nThe data that is passed into ggplot() is inherited if one is not provided\r\nThe function passed into the fun.data argument applies transformations to (a part of) that data (defaults to mean_se())\r\nThe result is passed into the geom provided in the geom argument (defaults to pointrange).\r\nIf the data contains all the required mapppings for the geom, the geom will be plotted.\r\nAnd to make things extra clear & to make stat_summary() less mysterious, we can explicitly spell out the two arguments fun.data and geom that we went over in this section.\r\n\r\n\r\nheight_df %>% \r\n ggplot(aes(x = group, y = height)) +\r\n stat_summary(\r\n geom = \"pointrange\",\r\n fun.data = mean_se\r\n )\r\n\r\n\r\n\r\n\r\nYou could also do fun.data = \"mean_se\" but I prefer the unquoted version because it make it extra clear that mean_se is a function, not a special parameter. It also keeps things consistent because if you want to pass in a custom function, they cannot be quoted.\r\n\r\n\r\n\r\nLook, it’s the same plot!\r\nPutting STAT to use\r\nNow we have arrived at the fun part.\r\nHere, I will demonstrate a few ways of modifying stat_summary() to suit particular visualization needs.\r\nFor this section, I will use a modified version of the penguins data that I loaded all the way up in the intro section (I’m just removing NA values here, nothing fancy).\r\n\r\n\r\nmy_penguins <- na.omit(penguins)\r\n\r\n\r\n\r\nAt no point in this section will I be modifying the data being piped into ggplot(). That is the beauty and power of stat.\r\n1. Error bars showing 95% confidence interval\r\nHere, we’re plotting the mean body_mass_g of penguins for each sex, with error bars that show the 95% confidence interval (a range of approx 1.96 standard errors from the mean).\r\n\r\n\r\nmy_penguins %>% \r\n ggplot(aes(sex, body_mass_g)) +\r\n stat_summary(\r\n fun.data = ~mean_se(., mult = 1.96), # Increase `mult` value for bigger interval!\r\n geom = \"errorbar\",\r\n )\r\n\r\n\r\n\r\n\r\nAs of {ggplot2} 3.3.0, you can use {rlang}-style anonymous functions. If you aren’t familiar, ~mean_se(., mult = 1.96) is the same as function(x) {mean_se(x, mult = 1.96)}\r\n\r\n\r\n\r\nThe transformed data used for the errorbar geom inside stat_summary():\r\n\r\n\r\nbind_rows(\r\n mean_se(my_penguins$body_mass_g[my_penguins$sex == \"female\"], mult = 1.96),\r\n mean_se(my_penguins$body_mass_g[my_penguins$sex == \"male\"], mult = 1.96),\r\n)\r\n\r\n\r\n y ymin ymax\r\n 1 3862 3761 3964\r\n 2 4546 4427 4665\r\n\r\n2. A color-coded bar plot of medians\r\nHere, we’re plotting the median bill_length_mm for each penguins species and coloring the groups with median bill_length_mm under 40 in pink.\r\n\r\n\r\ncalc_median_and_color <- function(x, threshold = 40) {\r\n tibble(y = median(x)) %>% \r\n mutate(fill = ifelse(y < threshold, \"pink\", \"grey35\"))\r\n}\r\n\r\nmy_penguins %>% \r\n ggplot(aes(species, bill_length_mm)) +\r\n stat_summary(\r\n fun.data = calc_median_and_color,\r\n geom = \"bar\"\r\n )\r\n\r\n\r\n\r\n\r\nCalculating summaries by group is automatically handled internally when you provide grouping variables (here, the species variable that’s mapped to x), so you don’t have to worry about that in your custom function.\r\n\r\n\r\n\r\nThe transformed data used for the bar geom inside stat_summary():\r\n\r\n\r\ngroup_split(my_penguins, species) %>%\r\n map(~ pull(., bill_length_mm)) %>% \r\n map_dfr(calc_median_and_color)\r\n\r\n\r\n\r\n\r\nThis is a more systematic way of mimicking the internal process of stat_summary(). Run each line incrementally see to what they do!\r\n\r\n # A tibble: 3 x 2\r\n y fill \r\n \r\n 1 38.8 pink \r\n 2 49.6 grey35\r\n 3 47.4 grey35\r\n\r\nNote how you can calculate non-required aesthetics in your custom functions (e.g., fill) and they also be used to make the geom!\r\n3. Pointrange plot with changing size\r\nHere, we’re plotting bill_depth_mm of penguins inhabiting different islands, with the size of each pointrange changing with the number of observations\r\n\r\n\r\nmy_penguins %>% \r\n ggplot(aes(species, bill_depth_mm)) +\r\n stat_summary(\r\n fun.data = function(x) {\r\n \r\n scaled_size <- length(x)/nrow(my_penguins)\r\n \r\n mean_se(x) %>% \r\n mutate(size = scaled_size)\r\n }\r\n )\r\n\r\n\r\n\r\n\r\nIf you don’t want to declare a new function in the environment just for one plot, you can just pass in an anonymous function to the fun.data argument. And of course, if it’s long, you should wrap it in function(x){}.\r\n\r\n\r\n\r\n\r\nLooking back, this is actually a cool plot because you can see how lower number of samples (smaller size) contributes to increased uncertainty (longer range) in the pointrange.\r\nThe transformed data used for the pointrange geom inside stat_summary():\r\n\r\n\r\ngroup_split(my_penguins, species) %>%\r\n map(~ pull(., bill_depth_mm)) %>% \r\n map_dfr(\r\n function(x) {\r\n \r\n scaled_size <- length(x)/nrow(my_penguins)\r\n \r\n mean_se(x) %>% \r\n mutate(size = scaled_size)\r\n }\r\n )\r\n\r\n\r\n y ymin ymax size\r\n 1 18.35 18.25 18.45 0.4384\r\n 2 18.42 18.28 18.56 0.2042\r\n 3 15.00 14.91 15.09 0.3574\r\n\r\nConclusion\r\nMain Ideas\r\nEven though the data is tidy, it may not represent the values you want to display\r\nThe solution is not to transform your already-tidy data so that it contains those values\r\nInstead, you should pass in your original tidy data into ggplot() as is and allow stat_*() functions to apply transformations internally\r\nThese stat_*() functions can be customized for both their geoms and their transformation functions, and works similarly to geom_*() functions in other regards\r\nIf you want to use your own custom function, make sure to check the documentation of that particular stat_*() function to check the variable/data type it requires.\r\nIf you want to use a different geom, make sure that your transformation function calculates all the required aesthetics for that geom\r\nSTAT vs. GEOM or STAT and GEOM?\r\nAlthough I have talked about the limitations of geom_*()s to demonstrate the usefulness of stat_*()s, both have their place. It’s about knowing when to use which; it’s not a question of either-or. In fact, they require each other - just like how stat_summary() had a geom argument, geom_*()s also have a stat argument. At a higher level, stat_*()s and geom_*()s are simply convenient instantiations of the layer() function that builds up the layers of ggplot.\r\nBecause this is important, I’ll wrap up this post with a quote from Hadley explaining this false dichotomy:\r\n\r\nUnfortunately, due to an early design mistake I called these either stat_() or geom_(). A better decision would have been to call them layer_() functions: that’s a more accurate description because every layer involves a stat and a geom.13\r\n\r\n\r\nJust to clarify on notation, I’m using the star symbol * here to say that I’m referencing all the functions that start with geom_ like geom_bar() and geom_point(). This is called the Kleene star and it’s used a lot in regex, if you aren’t familiar.↩︎\r\nYou could have bins of that are not of equal size. Or, you could have bins that bleed into each other to create a rolling window summary.↩︎\r\nYou could calculate the sum of raw values that are in each bin, or calculate proportions instead of counts↩︎\r\nIf you aren’t familiar already, “tidy” is a specific term of art↩︎\r\nThis quote is adapted from Thomas Lin Pedersen’s ggplot2 workshop video↩︎\r\nYes, you can still cut down on the code somewhat, but will it even get as succinct as what I show below with stat_summary()? (9/30 edit) Okay, I was kinda strawmaning, and Hadley(!) has correctly caught me on that. The bar-errorbar plot was not the best choice to demonstrate the benefits of stat_summary(), but I just wanted to get people excited about stat_*()! Sorry for the confusion/irritation!!↩︎\r\nThere’s actually one more argument against transforming data before piping it into ggplot. When you choose the variables to plot, say cyl and mpg in the mtcars dataset, do you call select(cyl, mpg) before piping mtcars into ggplot? No? Well then why would you transform your data beforehand if you can just have that be handled internally instead? It’s the same logic!↩︎\r\nIf you’re still skeptical, save the plot object to a variable like plot and call plot$layers to confirm that geom_pointrange was used to draw the plot.↩︎\r\nI personally don’t agree with this naming choice since mean is also the name of the base function↩︎\r\nThe function new_data_frame() is from {vctrs}. That last line of code in the function body is doing the same thing as data.frame(y = mean, ymin = mean - se, ymax = mean + se), but there’s less room for error the way it’s done in the source code.↩︎\r\nIf you read the documentation, the very first line starts with “stat_summary() operates on unique x or y …” (emphasis mine)↩︎\r\nThis second argument specifies which layer to return. Here, the pointrange layer is the first and only layer in the plot so I actually could have left this argument out.↩︎\r\nEmphasis mine. Source: https://cran.r-project.org/web/packages/ggplot2/vignettes/extending-ggplot2.html↩︎\r\n", + "preview": "posts/2020-09-26-demystifying-stat-layers-ggplot2/preview.png", + "last_modified": "2020-11-02T10:39:46-05:00", + "input_file": {}, + "preview_width": 240, + "preview_height": 278 + }, + { + "path": "posts/2020-09-23-tidytuesday-2020-week-39/", + "title": "TidyTuesday 2020 week 39", + "description": "Stacked area plot of the heights of Himalayan peaks attempted over the last century", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-23", + "categories": [ + "ggplot2", + "data visualization", + "tidytuesday" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n\r\n\r\n\r\nThings I learned\r\nHaving a nice background color for the plot (and generally just working with color)\r\nMargin options of various kinds in theme()\r\nUsing {scales}, pretty_breaks() in particular\r\nUsing {ragg} to draw and save high quality plots\r\nThings to improve\r\nThe subtitle is kinda boring (and the entire plot is a bit underwhelming)\r\nFigure out how to increase spacing between y-axis text and the plot (hjust is relative to each label, so doesn’t work)\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\n\r\n# DATA\r\n\r\ntuesdata <- tidytuesdayR::tt_load(\"2020-09-22\")\r\n\r\nclimb_data <- tuesdata$expeditions %>% \r\n left_join(tuesdata$peaks, by = \"peak_name\") %>% \r\n select(peak = peak_name, year, height = height_metres) %>% \r\n arrange(-height) %>% \r\n mutate(height_group = fct_inorder(case_when(peak == \"Everest\" ~ \"Mt. Everest (8850m)\",\r\n between(height, 8000, 8849) ~ \"> 8000m\",\r\n between(height, 7000, 7999) ~ \"7999m ~ 7000m\",\r\n between(height, 6000, 6999) ~ \"6999m ~ 6000m\",\r\n TRUE ~ \"< 6000m\"))\r\n ) %>% \r\n count(five_years = round(year/5) * 5, height_group) %>% \r\n filter(five_years >= 1920) %>% \r\n complete(five_years, height_group, fill = list(n = 0)) %>% \r\n group_by(five_years) %>% \r\n mutate(prop = n / sum(n)) %>% \r\n ungroup()\r\n\r\n\r\n# PLOT\r\n\r\nmountain_palette <- c(\"#6E86A6\", \"#95A2B3\", \"#5C606A\", \"#44464E\", \"#3D3737\")\r\n\r\nclimb_plot <- climb_data %>% \r\n ggplot(aes(five_years, prop)) +\r\n geom_area(aes(fill = height_group, color = height_group)) +\r\n scale_fill_manual(values = mountain_palette) +\r\n scale_color_manual(values = mountain_palette) +\r\n coord_cartesian(xlim = c(1920, 2020), expand = FALSE) +\r\n scale_x_continuous(breaks = scales::pretty_breaks(11)) +\r\n scale_y_continuous(labels = scales::percent) +\r\n labs(\r\n title = \"Himalayan Peaks Attempted Over Time\",\r\n subtitle = \"Over 1/4th of all expeditions were to Mount Everest\",\r\n x = NULL, y = NULL, fill = NULL, color = NULL,\r\n caption = \"By: @yjunechoe | Source: The Himalayan Database\"\r\n ) +\r\n theme_classic(base_family = \"Futura Hv BT\", base_size = 16) +\r\n theme(\r\n plot.title.position = \"plot\",\r\n plot.title = element_text(size = 28, color = \"white\", family = \"Lora\", face = \"bold\"),\r\n plot.subtitle = element_text(size = 14, color = \"white\", face = \"italic\"),\r\n plot.margin = margin(2, 2.5, 2, 2, 'cm'),\r\n plot.caption = element_text(color = \"white\", family = \"Roboto Mono\", hjust = 1.15, vjust = -13),\r\n legend.position = \"top\",\r\n legend.direction = \"horizontal\",\r\n legend.text = element_text(color = \"white\"),\r\n legend.background = element_rect(fill = NA),\r\n axis.text = element_text(color = \"white\"),\r\n axis.text.y = element_text(vjust = -.1),\r\n axis.text.x = element_text(vjust = -2),\r\n axis.ticks = element_blank(),\r\n axis.line = element_blank(),\r\n panel.background = element_blank(),\r\n plot.background = element_rect(fill = \"#606F84\", color = NA)\r\n )\r\n\r\n\r\n# SAVE\r\n\r\npngfile <- fs::path(getwd(), \"plot.png\")\r\nragg::agg_png(\r\n pngfile,\r\n width = 60,\r\n height = 36,\r\n units = \"cm\",\r\n res = 300,\r\n scaling = 2\r\n)\r\nplot(climb_plot); invisible(dev.off())\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-09-23-tidytuesday-2020-week-39/preview.png", + "last_modified": "2020-11-01T19:03:42-05:00", + "input_file": {}, + "preview_width": 7086, + "preview_height": 4251 + }, + { + "path": "posts/2020-09-20-plot-makeover-1/", + "title": "Plot Makeover #1", + "description": "Flattening a faceted grid for strictly horizontal comparisons", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-20", + "categories": [ + "plot makeover", + "data visualization", + "ggplot2" + ], + "contents": "\r\n\r\nContents\r\nBefore\r\nMy Plan\r\nAfter\r\nPoint-line plot\r\nBar plot\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nThis is the first installment of plot makeover where I take a plot in the wild and make very opinionated modifications to it.\r\nBefore\r\nOur plot-in-the-wild comes from the recent AMLAP 2020 conference, where I presented my thesis research and had the opportunity to talk with and listen to expert psycholinguists around the world. The plot that I’ll be looking at here is Figure 3 from the abstract of a work by E. Matthew Husband and Nikole Patson (Husband and Patson 2020).\r\n\r\n\r\n\r\nFigure 1: Plot from Husband and Patson (2020)\r\n\r\n\r\n\r\nWhat we have is 6 pairs of barplots with error bars, laid out in a 2-by-3 grid. The total of 12 bars are grouped at three levels which are mapped in the following way:\r\nFirst level is mapped to the grid column.\r\nSecond level is mapped to the grid row.\r\nThird level is mapped to the x-axis.\r\nTo get a better sense of what they did, and to make data for the plot makeover, I have recreated the original plot below:1\r\n1. Data\r\n\r\n\r\nlibrary(tidyverse)\r\ndf <- crossing(level_1 = fct_inorder(c(\"Within\", \"Between\")),\r\n level_2 = fct_inorder(c(\"Some\", \"Number\", \"Or\")),\r\n level_3 = factor(c(\"Strong\", \"Weak\")))\r\ndf$barheight <- c(.63, .35, .72, .55, .61, .15, .60, .55, .52, .63, .17, .16)\r\n\r\ndf\r\n\r\n\r\n\r\n\r\nThe numbers for barheight were eyeballed from looking at the original plot, of course.\r\n\r\n # A tibble: 12 x 4\r\n level_1 level_2 level_3 barheight\r\n \r\n 1 Within Some Strong 0.63\r\n 2 Within Some Weak 0.35\r\n 3 Within Number Strong 0.72\r\n 4 Within Number Weak 0.55\r\n 5 Within Or Strong 0.61\r\n 6 Within Or Weak 0.15\r\n 7 Between Some Strong 0.6 \r\n 8 Between Some Weak 0.55\r\n 9 Between Number Strong 0.52\r\n 10 Between Number Weak 0.63\r\n 11 Between Or Strong 0.17\r\n 12 Between Or Weak 0.16\r\n\r\n2. Plot\r\n\r\n\r\ndf %>% \r\n ggplot(aes(level_3, barheight)) +\r\n geom_col(\r\n aes(fill = level_3),\r\n show.legend = FALSE\r\n ) +\r\n geom_errorbar(\r\n aes(ymin = barheight - .05, ymax = barheight + .05),\r\n width = .1) +\r\n facet_grid(level_2 ~ level_1) +\r\n theme_bw() +\r\n scale_fill_manual(values = c('grey40', 'grey80')) +\r\n ylim(0, 1) +\r\n labs(\r\n y = \"Proportion of Strong Responses\",\r\n x = \"Prime Type\") +\r\n theme_bw()\r\n\r\n\r\n\r\n\r\n\r\nThe original plot for comparison:\r\n\r\n\r\n\r\nMy Plan\r\nMajor Changes:\r\nFlatten the grid in some way so that everything is laid out left-to-right and you can make comparisons horizontally.\r\nCap the y axis to make it clear that the values (proportions) can only lie between 0 and 1.\r\nMinor Changes:\r\nRemove grid lines\r\nIncrease space between axis and axis titles.\r\nRemove boxes around strip labels\r\nMake strip (facet) labels larger and more readable.\r\nIncrease letter spacing (probably by changing font)\r\nAfter\r\nI actually couldn’t settle on one final product2 so here are two plots that incorporate the changes that I wanted to make. I think that both look nice and you may prefer one style over the other depending on what relationships/comparisons you want your graph to emphasize.\r\nPoint-line plot\r\nI got a suggestion that the groups could additionally be mapped to shape for greater clarity, so I’ve incorporated that change.3\r\n\r\n\r\n\r\n\r\n\r\ndodge <- position_dodge(width = .5)\r\n\r\ndf %>% \r\n mutate(level_3 = as.numeric(level_3)) %>% \r\n ggplot(aes(x = level_3, y = barheight, group = level_1)) +\r\n geom_errorbar(\r\n aes(ymin = barheight - .05, ymax = barheight + .05),\r\n width = .2,\r\n position = dodge\r\n ) +\r\n geom_line(\r\n aes(linetype = level_1),\r\n position = dodge,\r\n show.legend = FALSE\r\n ) +\r\n geom_point(\r\n aes(shape = level_1, fill = level_1),\r\n size = 1.5,\r\n stroke = .6,\r\n position = dodge\r\n ) + \r\n scale_fill_manual(values = c(\"black\", \"white\")) +\r\n scale_shape_manual(values = c(21, 24)) +\r\n facet_wrap(~ level_2) +\r\n scale_x_continuous(\r\n breaks = 1:2,\r\n labels = levels(df$level_3),\r\n expand = expansion(.2),\r\n ) +\r\n scale_y_continuous(\r\n limits = c(0, 1),\r\n expand = expansion(c(0, .1))\r\n ) +\r\n lemon::coord_capped_cart(left = \"both\") +\r\n guides(\r\n fill = guide_none(),\r\n shape = guide_legend(\r\n title = NULL,\r\n direction = \"horizontal\",\r\n label.theme = element_text(size = 10, family = \"Montserrat\"),\r\n override.aes = list(fill = c(\"black\", \"white\"))\r\n )\r\n ) +\r\n labs(\r\n y = \"Strong Responses\",\r\n x = \"Prime Type\",\r\n linetype = \"Category\"\r\n ) +\r\n ggthemes::theme_clean(base_size = 14) +\r\n theme(\r\n text = element_text(family = \"Montserrat\"),\r\n legend.position = c(.18, .87),\r\n legend.background = element_rect(color = NA, fill = NA),\r\n strip.text = element_text(size = 13),\r\n plot.margin = margin(5, 5, 5, 5, 'mm'),\r\n axis.title.x = element_text(vjust = -3),\r\n axis.title.y = element_text(vjust = 5),\r\n plot.background = element_blank(),\r\n panel.grid.major.y = element_blank()\r\n )\r\n\r\n\r\n\r\nBar plot\r\n\r\n\r\n\r\n\r\n\r\ndodge <- position_dodge(width = .5)\r\n\r\ndf %>% \r\n mutate(level_3 = as.numeric(level_3)) %>% \r\n ggplot(aes(x = level_3, y = barheight, group = level_1)) +\r\n geom_col(position = dodge, width = .5, color = 'white', aes(fill = level_1)) +\r\n scale_fill_manual(values = c(\"grey30\", \"grey60\")) +\r\n geom_errorbar(\r\n aes(ymin = barheight - .05, ymax = barheight + .05),\r\n width = .2,\r\n position = dodge\r\n ) +\r\n facet_wrap(~ level_2) +\r\n scale_x_continuous(\r\n breaks = 1:2,\r\n labels = levels(df$level_3),\r\n expand = expansion(.2),\r\n ) +\r\n ylim(0, 1) +\r\n lemon::coord_capped_cart(left = \"both\") +\r\n labs(\r\n y = \"Strong Responses\",\r\n x = \"Prime Type\",\r\n fill = NULL\r\n ) +\r\n ggthemes::theme_clean(base_size=14) +\r\n theme(\r\n text = element_text(family = \"Montserrat\"),\r\n legend.text = element_text(size = 10),\r\n legend.key.size = unit(5, 'mm'),\r\n legend.direction = \"horizontal\",\r\n legend.position = c(.17, .85),\r\n legend.background = element_blank(),\r\n strip.text = element_text(size = 14),\r\n axis.ticks.x = element_blank(),\r\n axis.title.x = element_text(vjust = -3),\r\n axis.title.y = element_text(vjust = 5),\r\n panel.grid.major.y = element_blank(),\r\n plot.background = element_blank(),\r\n plot.margin = margin(5, 5, 5, 5, 'mm')\r\n )\r\n\r\n\r\n\r\n\r\nIn this second version, I removed guides() and distributed its arguments across labs() and theme(). I kinda like this layout of having a fat theme(). It’s also not too hard to read if you group and sort the arguments.\r\n\r\n\r\n\r\nHusband, E. Matthew, and Nikole Patson. 2020. Priming of Implicatures Within and Between Categories: The Case of or. AMLaP2020. https://amlap2020.github.io/a/272.pdf.\r\n\r\n\r\nBut note that this is likely not how the original plot was generated: the authors were likely feeding ggplot2 with the raw data (involving 1s and 0s in this case), but here I am just grabbing the summary statistic that was mapped to the bar aesthetic (hence my decision to name the y variable barheight).↩︎\r\nI ran the first plot by a friend who has a degree in design, and she recommended several changes that eventually ended up being the second plot. Some major pointers were removing border lines from the legend, removing x-axis tick marks, and applying color/shade.↩︎\r\nThe plot used to look like this: ↩︎\r\n", + "preview": "posts/2020-09-20-plot-makeover-1/plot-makeover-1_files/figure-html5/after_bar_plot-1.png", + "last_modified": "2021-06-11T03:41:53-04:00", + "input_file": {}, + "preview_width": 1248, + "preview_height": 768 + }, + { + "path": "posts/2020-09-14-tidytuesday-2020-week-38/", + "title": "TidyTuesday 2020 week 38", + "description": "Visualizing two decades of primary and secondary education spending with {gt}", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-14", + "categories": [ + "tables", + "data visualization", + "tidytuesday" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\nI had difficulty embedding an HTML table without overriding its styles so the table is also available on its own here.\r\n\r\n\r\n\r\nThings I learned\r\nBasics of working with tables and {gt}1\r\nPutting different font styles together in a nice way\r\nThings to improve\r\nSummarize the data a bit more so the table isn’t huge\r\nAdd conditional formatting (learn how tab_style() and tab_options() work)\r\nFigure out how to save {gt} tables into pdf or png\r\nFigure out how to include an html table without overriding css styles\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(gt)\r\n\r\nkids <- tidytuesdayR::tt_load(\"2020-09-15\")$kids\r\n\r\n\r\n# TABLE DATA\r\n\r\nstate_regions <- setNames(c(as.character(state.region), \"Northeast\"), c(state.name, \"District of Columbia\"))\r\n\r\nkids_tbl_data <- kids %>% \r\n filter(variable == \"PK12ed\") %>%\r\n mutate(region = state_regions[state]) %>% \r\n select(region, state, year, inf_adj_perchild) %>% \r\n pivot_wider(names_from = year, values_from = inf_adj_perchild) %>%\r\n mutate(Trend = NA) \r\n\r\n\r\n# SPARKLINE\r\n\r\nplotter <- function(data){\r\n data %>% \r\n tibble(\r\n year = 1997:2016,\r\n value = data\r\n ) %>% \r\n ggplot(aes(year, value)) +\r\n geom_line(size = 10, show.legend = FALSE) +\r\n theme_void() +\r\n scale_y_continuous(expand = c(0, 0))\r\n}\r\n\r\nspark_plots <- kids_tbl_data %>% \r\n group_split(state) %>% \r\n map(~ flatten_dbl(select(.x, where(is.numeric)))) %>% \r\n map(plotter)\r\n\r\n\r\n# TABLE\r\n\r\nkids_tbl <- kids_tbl_data %>% \r\n gt(\r\n groupname_col = 'region',\r\n rowname_col = 'state'\r\n ) %>% \r\n fmt_number(\r\n columns = 3:22\r\n ) %>% \r\n summary_rows(\r\n groups = TRUE,\r\n columns = 3:22,\r\n fns = list(Average = ~mean(.))\r\n ) %>% \r\n text_transform(\r\n locations = cells_body(vars(Trend)),\r\n fn = function(x){\r\n map(spark_plots, ggplot_image, height = px(15), aspect_ratio = 4)\r\n }\r\n ) %>%\r\n tab_header(\r\n title = md(\"**State-by-State Spending on Primary and Secondary Education over 20 years**\"),\r\n subtitle = md(\"*$1000s per child adjusted for inflation*\")\r\n ) %>% \r\n tab_source_note(\r\n md(\"**By**: @yjunechoe
    \r\n **Inspiration**: @thomas_mock
    \r\n **Data**: Urban Institute | {tidykids} by Joshua Rosenberg\")\r\n ) %>% \r\n tab_style(\r\n style = list(\r\n cell_text(font = \"Futura MdCn BT\")\r\n ),\r\n locations = list(\r\n cells_title(groups = \"title\")\r\n )\r\n ) %>%\r\n tab_options(\r\n table.width = 50,\r\n heading.align = \"left\",\r\n heading.title.font.size = 72,\r\n heading.subtitle.font.size = 32,\r\n row_group.font.size = 42,\r\n row_group.font.weight = 'bold',\r\n row_group.border.top.color = \"black\",\r\n row_group.border.bottom.color = \"black\",\r\n table.border.top.color = \"black\",\r\n heading.border.bottom.color = \"white\",\r\n heading.border.bottom.width = px(10),\r\n table.font.names = \"Roboto\",\r\n column_labels.font.size = 20,\r\n column_labels.border.bottom.color = \"black\",\r\n column_labels.border.bottom.width= px(3),\r\n summary_row.border.color = \"black\", \r\n summary_row.background.color = \"#c0c5ce\",\r\n table.border.bottom.color = \"black\"\r\n )\r\n\r\n\r\n\r\n\r\nMany thanks to Thomas Mock’s blog posts on {gt} (1) (2), a well as to the developers of {gt} for what I think is one of the most comprehensive vignette I’ve ever seen for a package!↩︎\r\n", + "preview": "posts/2020-09-14-tidytuesday-2020-week-38/preview.png", + "last_modified": "2020-11-05T11:08:39-05:00", + "input_file": {}, + "preview_width": 1703, + "preview_height": 2203 + }, + { + "path": "posts/2020-09-12-videos-in-reactable/", + "title": "Embedding videos in {reactable} tables", + "description": "Pushing the limits of expandable row details", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-12", + "categories": [ + "tables", + "data visualization" + ], + "contents": "\r\n\r\n\r\n\r\nIn a {reactable} table, you can have a row expand to reveal more details by supplying the details argument with a function returning an image, raw html, another reactable table, etc. There are many examples of this in the package vignette, and they give you a good sense of just how flexible and powerful this feature is.\r\nMy first reaction to this was that it seemed like just about anything that can be displayed on a web page can be embedded in the expandable details. So what about something very unusual like… videos? Can {reactable} handle it? Are there potential usecases of this?\r\nAnnotated #tidytuesday screencasts\r\nWhile entertaining this idea, I remembered coming across a tweet by Alex Cookson with a link to a very detailed spreadsheet containing timestamped notes of David Robinson’s live #tidytuesday screencasts.\r\n\r\n\r\nAnyone other #rstats people find @drob's #TidyTuesday screencasts useful?I made a spreadsheet with timestamps for hundreds of specific tasks he does: https://t.co/HvJbLk1chdUseful if, like me, you keep going back and ask, “Where in the video did he do [this thing] again?”\r\n\r\n— Alex Cookson (@alexcookson) January 13, 2020\r\n\r\nSo I turned the spreadsheet into a {reactable} table with rows that can expand to reveal a Youtube video at the timestamp. I actually think this makes a really cool use case - it’s easier here than in Google Spreadsheet to navigate around the table with pagination and search bar, and you don’t need to constantly open and close Youtube videos in new windows (in fact, you can keep multiple videos open across rows here!).\r\nTry it out for yourself!\r\n\r\n\r\n{\"x\":{\"tag\":{\"name\":\"Reactable\",\"attribs\":{\"data\":{\"Screencast\":[\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"College Majors and Income\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"Horror Movie Profits\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"R Downloads\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"US Wind Turbines\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Malaria Incidence\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Thanksgiving Dinner\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Maryland Bridges\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Medium Articles\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"Riddler: Monte Carlo Simulation\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"NYC Restaurant Inspections\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Riddler: Simulating a Week of Rain\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"Dolphins\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TidyTuesday Tweets\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"TV Golden Age\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"Space Launches\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Incarceration\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US Dairy Consumption\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"US PhDs\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"French Train Delays\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Women in the Workplace\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Board Game Reviews\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Pet Names\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Seattle Bike Counts\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Tennis Tournaments\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Bird Collisions\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Student-Teacher Ratios\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Nobel Prize Winners\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Plastic Waste\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Wine Ratings\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Ramen Reviews\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Media Franchise Revenue\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Women's World Cup\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Bob Ross Paintings\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Simpsons Guest Stars\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Pizza Ratings\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Car Fuel Efficiency\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"Horror Movies\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"NYC Squirrel Census\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"CRAN Package Code\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"Riddler: Spelling Bee Honeycomb\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"The Office\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"COVID-19 Open Research Dataset (CORD-19)\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"CORD-19 Data Package\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"R trick: Creating Pascal's Triangle with accumulate()\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Riddler: Simulating Replacing Die Sides\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Beer Production\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Riddler: Simulating a Non-increasing Sequence\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Tour de France\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"Riddler: Simulating a Branching Process\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"GDPR Violations\",\"Broadway Musicals\",\"Broadway Musicals\",\"Broadway Musicals\",\"Broadway Musicals\",\"Broadway Musicals\",\"Broadway Musicals\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Riddler: Simulating and Optimizing Coin Flipping\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Animal Crossing\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Volcano Eruptions\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Beach Volleyball\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"Cocktails\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American Achievements\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"African-American History\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"Caribou Locations\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"X-Men Comics\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Coffee Ratings\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Australian Animal Outcomes\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"Palmer Penguins\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"European Energy\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Plants in Danger\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Chopped\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Global Crop Yields\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Friends\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Government Spending on Kids\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Himalayan Climbers\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"Beyonce and Taylor Swift Lyrics\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"NCAA Women's Basketball\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"Great American Beer Festival\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"IKEA Furniture\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Historical Phones\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Riddler: Simulating a Circular Random Walk\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Ninja Warrior\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Big Mac Index\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Transit Costs\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Art Collections\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"Kenya Census\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\",\"HBCU Enrollment\"],\"Date\":[\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-15\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-23\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-10-30\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-06\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-12\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-21\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-11-27\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-04\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-02\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-11\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-12\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2018-12-18\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-07\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-09\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-15\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-25\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-01-29\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-22\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-02-26\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-05\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-15\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-03-16\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-05\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-04-09\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-03\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-10\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-24\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-27\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-05-31\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-04\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-06-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-07-22\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-12\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-08-30\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-01\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-15\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-10-22\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-11-01\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2019-12-30\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-01-06\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-16\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-18\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-19\",\"2020-03-29\",\"2020-03-29\",\"2020-03-29\",\"2020-03-29\",\"2020-03-29\",\"2020-03-29\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-03-30\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-01\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-06\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-07\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-13\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-21\",\"2020-04-28\",\"2020-04-28\",\"2020-04-28\",\"2020-04-28\",\"2020-04-28\",\"2020-04-28\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-03\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-05\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-12\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-19\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-05-26\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-09\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-16\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-23\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-06-30\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-07\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-21\",\"2020-07-20\",\"2020-07-21\",\"2020-07-22\",\"2020-07-23\",\"2020-07-24\",\"2020-07-25\",\"2020-07-26\",\"2020-07-27\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-07-28\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-04\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-18\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-08-25\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-01\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-08\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-15\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-22\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-09-29\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-06\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-10-20\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-03\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-10\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-11-23\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-15\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2020-12-22\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-05\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-12\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-01-19\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\",\"2021-02-02\"],\"Timestamp\":[105,440,535,575,850,1065,1245,1305,1710,1800,2180,2230,2415,2730,2830,2920,2995,3070,3365,3485,3890,4140,4205,4250,4555,170,465,530,760,875,970,1160,1290,1450,1560,1715,1970,2480,2755,3105,3205,3490,3655,320,455,590,605,740,1040,1230,1340,1860,2120,2195,2285,2320,2345,2860,3135,3475,230,300,370,455,645,690,855,1180,1560,1995,2280,2740,2820,2935,3405,3475,3705,3875,3940,165,850,910,1120,1190,1240,1310,1485,1610,1710,1975,2145,2200,2310,2340,2555,2850,3085,3130,3315,3465,3720,3755,3835,250,460,685,785,840,870,1010,1075,1110,1315,1375,1425,1620,1680,1725,1825,1970,2135,2175,2435,2550,2730,2780,2945,3100,3180,3205,3305,3465,3535,3605,555,610,750,940,1195,1295,1635,1745,1875,2070,2220,2300,2755,2915,3030,3070,3125,3280,3305,3360,3735,3875,3890,3935,4150,340,415,490,540,590,725,755,875,960,1000,1070,1220,1355,1515,1690,1830,2040,2100,2320,2410,2450,2595,2685,2750,2865,2940,2995,3065,3155,3275,3620,190,240,405,425,490,600,650,735,835,905,945,1080,1140,1170,1355,1470,1535,1555,1585,1635,1705,1805,1815,1910,1945,2010,2045,2110,2180,2225,2385,2410,2430,2485,2770,2990,3140,3235,3310,3395,3700,3810,3960,1125,1275,1500,1580,1620,1725,2025,2520,2565,3120,3180,3330,3480,3495,3690,3720,3840,80,155,195,260,330,430,525,620,685,750,940,1030,385,510,595,710,930,960,1045,1150,1275,1405,1445,1625,1890,1990,2400,2785,2850,2910,3010,3030,3140,3265,3350,3445,3610,80,175,325,350,485,660,695,775,885,960,1065,1100,1520,1820,1890,2025,2275,2460,2550,2575,2650,2790,3060,3395,3555,3645,3835,4045,4125,4340,4500,145,450,610,930,1225,1250,1430,1700,1890,2030,2190,2340,2435,2525,2750,2915,3420,3530,3595,3630,3820,3975,280,380,910,1005,1095,1150,1265,1920,2105,2135,2235,2570,2595,2840,2880,3090,3395,270,465,685,855,1120,1455,1580,1680,1985,2010,2470,2540,2625,2895,3010,3290,3425,170,280,380,430,500,630,790,890,950,1185,1280,1330,1560,1670,1690,1785,1850,1930,2100,2265,2420,2455,2515,2855,3085,3125,3360,3440,195,445,500,560,610,720,830,1010,1130,1145,1315,1390,1520,1650,1690,2130,2380,620,865,930,990,1065,1125,1560,1720,2090,2375,2705,3035,3100,3140,3210,350,555,590,740,1070,1525,1800,2000,2090,2595,2875,3245,170,445,525,610,955,975,1195,1250,1375,1505,1655,1710,1850,2045,2245,2295,2405,2500,2655,2745,2915,3095,3315,3525,3655,3675,160,260,390,595,675,755,970,1025,1075,1135,1240,1410,1440,1515,1630,1785,1915,2065,2265,2370,2560,2695,2760,2850,2960,3000,3235,375,495,720,900,1185,1365,1590,2520,2625,2730,2850,3015,3170,3290,300,675,780,900,930,995,1065,1135,1215,1230,1470,1820,2100,2385,2460,2610,2880,2940,3105,3175,3260,3850,165,450,570,1245,1395,1620,1740,1920,2310,2520,2655,2805,450,755,1060,1140,1400,1545,1675,1915,1935,2910,3110,3150,3270,3440,3480,4010,4080,4210,120,210,540,650,970,1010,1370,1420,1575,2025,2185,2665,2955,3910,4005,4220,105,1010,1305,1740,1770,1920,2025,2175,2370,2850,3180,195,555,780,1020,1290,1485,1665,1845,1935,2010,2085,2205,2400,2700,2805,2820,2895,2985,3060,3195,3240,3405,3510,3735,3810,4095,4230,4650,4830,105,175,255,335,465,550,590,690,785,885,940,1040,1135,1175,1280,1345,1385,1540,1605,1655,1755,1815,1865,1915,1960,2050,2265,2880,3065,3115,3155,3280,3360,3555,555,660,870,1170,1240,1560,1600,1770,1790,2015,2430,2480,2525,2645,2675,2765,2845,3020,3095,3225,135,225,360,840,1590,1710,2400,4185,100,110,155,210,280,840,935,1200,1270,1335,1370,1685,1710,1815,1915,2075,2090,2215,2295,2395,2600,2880,3410,3465,255,475,595,885,970,1085,1250,1580,1885,2000,2245,2335,2570,2645,2890,3400,285,545,660,750,930,1155,1230,1335,1395,1560,1650,1880,2190,2385,2475,2535,2715,3315,3480,3555,3750,200,600,1080,1485,1620,1715,1800,1845,1910,2010,2110,2190,2275,2530,2865,2910,3310,3400,255,480,585,710,770,810,940,1080,1240,1280,1380,1490,1550,1615,1680,1750,2045,2225,2470,2555,2745,345,405,540,630,765,810,990,1170,1245,1525,1620,1700,1815,1840,1890,1965,2080,2275,2325,2390,2490,2535,2630,2760,2810,2915,3090,3190,3410,3500,270,575,680,690,960,1200,1575,2040,2160,2585,3280,3470,3525,3935,120,155,205,235,645,850,1045,1555,1670,1795,2525,2615,2715,2850,3910,4755,105,145,250,290,355,430,530,615,765,845,1150,1210,1345,1540,1945,2225,2275,2485,2565,3140,3175,3505,3620,3715,3750,3830,3935,3955,4165,4255,55,175,470,585,640,700,790,995,1060,1200,1370,1480,1730,1940,2220,2385,2605,2670,2740,3125,3210,3570,3985,4755,70,185,340,445,510,540,615,895,1175,1490,1570,1610,1655,1940,2390,2850,3475,3570,3780,4125,4160,4570,4630,4695,4830,4945,70,90,175,275,385,485,45,125,230,420,435,460,605,635,680,700,755,810,1000,1040,1080,265,280,445,560,830,885,925,1090,1320,1440,1515,1655,1705,2050,2485,2805,2935,3065,3150,3340,3505,3820,3940,4010,4150,140,200,220,295,350,455,570,785,790,930,985,235,535,1310,1445,1530,1650,1860,2070,2475,2525,2870,2890,3025,3090,3360,3500,3760,35,160,260,325,425,455,560,655,720,795,1030,1225,1385,1430,1560,1855,2045,2325,2760,245,335,375,390,425,495,535,665,915,940,1055,1170,1650,1915,1975,2328,2425,2474,2575,2845,495,840,1310,1500,1520,2485,135,180,440,615,685,740,855,915,990,1205,1290,1320,1365,1425,1530,1785,305,470,540,635,750,880,1350,1620,1710,1845,2070,2215,2260,2455,2690,2765,2900,3120,3235,3455,420,590,770,930,985,1110,1450,1635,1900,1925,2045,2090,2235,2370,2790,2925,3020,3055,3580,330,440,480,635,770,915,1225,1280,1365,1425,1475,1525,1710,2055,2100,2520,2965,3270,3870,380,460,690,960,1185,1515,1600,1733,1909,1950,2065,2195,2885,3152,3420,500,695,745,950,1100,1170,1230,1345,1565,2035,2065,2115,2515,2955,3520,415,480,620,780,1040,1085,1615,1745,1780,2125,2900,3060,3320,3440,3540,240,540,830,1500,1635,2115,2235,2585,3600,445,595,805,1115,1325,1390,1805,2070,2360,2700,2760,2845,3165,3275,3600,495,530,595,700,755,920,1235,1290,1390,1475,1575,1640,1775,2260,2420,2465,2520,2665,3035,80,270,380,420,555,730,783,850,970,1170,1305,1545,1633,1735,1775,1787,2245,2350,2565,3345,3695,677,880,921,1070,1105,1200,2375,2605,3185,3940,4245,4780,110,445,540,610,630,995,1085,1210,1470,1760,2000,2445,2700,2820,2900,3160,3600,120,300,485,720,895,1145,1615,1700,2730,2975,3000,3060,3470,320,390,435,435,655,655,920,1090,1090,1185,1260,1400,1580,1680,1815,1915,2075,2140,2210,4645,215,400,460,505,580,710,2000,2210,2700,2760,2870,3025,3410,450,575,727,750,945,1235,1295,1605,2045,2520,3255,3625,375,960,1415,1645,2225,3050,3262,3460,3722,3900,180,530,680,870,1020,1280,1595,1680,2130,2320,2395,2490,2780,2830,3045,3390,3585,3810,470,490,675,765,780,915,1065,1245,1390,1620,1695,1710,2080,2320,2470,2680,3045,3185,3255,3715,900,995,1235,1255,1300,1935,2085,2390,2530,2575,2825,3260,3395,3590,500,685,745,745,805,870,900,1165,1285,1565,1680,1780,1985,2015,2130,2200,2375,2505,2680,2835,3025,3180,3300,270,360,420,480,540,665,770,1160,1260,1460,1530,1605,1790,1965,2660,2880,3180,3380,3470,135,450,570,840,1070,1185,1235,1265,1770,1860,2120,2120,2120,2300,2345,2392,2545,3000,3600,85,150,220,310,495,820,1590,1720,1815,2325,155,400,545,640,650,965,1100,1390,1830,2260,2730,3022,3565,345,355,390,405,420,510,800,905,1690,2045,2140,2305,2320,2820,3185,3485,3650,285,380,435,550,620,820,935,1155,1455,1895,1980,2440,2935,3480,3625,115,245,290,470,625,835,860,995,1115,1295,1760,2305,2495,2655,2765,2905,3060,3380,3550,135,275,300,315,325,410,455,455,540,550,620,675,710,885,913,930,1015,1080,1180,1180,1180,1655,1695,2100,2180,2245,2600,3115,3560,165,210,210,260,355,380,660,750,895,970,1030,1090,1130,1215,1285,1495,1535,1765,2165,2265,2330,2435,2660,2940,2960,3480],\"Link\":[\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"nx5yhXAQLxw\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"3-DRwg9yeNA\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"nms9F-XubJU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"O1oDIQV6VKU\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"5_6O2oDy5Jk\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"rxJZT0duwfU\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"kzM-4jMh9Qs\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"C69QyycHsgE\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"pBGMt28xgvk\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"em4FXPf4H-Y\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"TDzd73z8thU\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KiqpX-gNIS4\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"KE9ItC3doEU\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"oYGi2wgSJaM\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"ZyPrP_Yo1BA\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"78kv808ZU6o\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"13iG_HkEPVc\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"KzRP40PzopY\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"bmaigtpKyiM\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"fv9SQ4IFNr4\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"qirKGdQvy9U\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"EF4A4OtQprg\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"sBho2GJE5lc\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"YWUCUfEeNJI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"zjWm__nFLXI\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"NoUHdrailxA\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"yWSpLfmES7w\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"BRdLOYtJk9o\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"AQzZNIyjyWM\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"tCa2di7aEP4\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"1xsbTs9-a50\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"ZOQSuapvHqA\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"sD993H5FBIY\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"EYuuAGDeGrQ\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"Mkac8DHScps\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"RpeioixHOHw\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"yFRSTlk3kRQ\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"6GV9sAD6Pi0\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"dr4qw8o0nYU\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"wFZhuQEfEYA\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"_IvAubTDQME\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"-5HYdBq_PTM\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"F4oUJp76KUY\",\"rUK9Wz9B2n0\",\"rUK9Wz9B2n0\",\"rUK9Wz9B2n0\",\"rUK9Wz9B2n0\",\"rUK9Wz9B2n0\",\"rUK9Wz9B2n0\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"XEsNpxl5b1M\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"1R4X09w7tQ8\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"aR6jf6ZzlFk\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"vT-DElIaKtE\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"QtThluGted0\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"EVvnnWKO_4w\",\"OhY5ZaILRpg\",\"OhY5ZaILRpg\",\"OhY5ZaILRpg\",\"OhY5ZaILRpg\",\"OhY5ZaILRpg\",\"OhY5ZaILRpg\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"nmS3UZSWYRo\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"Xt7ACiedRRI\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"pZINGjQ86Hc\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"MfDdmsW3OMo\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"EC0SVkFB2OU\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"-W-OopvhNPo\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"2L-jA-Me3zg\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"7G7SVODhVo4\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"NY0-IFet5AM\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"-1x8Kpyndss\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"E2amEz_upzU\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"ImpXawPNCfM\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"Rcmu5e-9FSc\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"f7Rc1bvMgZY\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"6V0vAx2Km7U\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"0uqAhIiK9Rc\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"bgcBEBqVnx8\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"dHRPrVsnNwo\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"WT7FMn-_jPY\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"vYbDyfv_v4Q\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"-RD8GNCNsCk\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"BV_afpCDQ70\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"lY0YLDZhT88\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"pJPqAIb8MKA\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"b1oKh9eeqkY\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"4AhXvMsCooM\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"pxJ5wtxL5Kw\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"8jNQzce13SE\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"AqwA5EJfLXo\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"dM_0zjj4TtM\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\",\"TSG74voJQ3E\"],\"Description\":[\"Using read_csv function to import data directly from Github to R (without cloning the repository)\",\"Creating a histogram (geom_histogram), then a boxplot (geom_boxplot), to explore the distribution of salaries\",\"Using fct_reorder function to sort boxplot of college majors by salary\",\"Using dollar_format function from scales package to convert scientific notation to dollar format (e.g., \\\"4e+04\\\" becomes \\\"$40,000\\\")\",\"Creating a dotplot (geom_point) of 20 top-earning majors (includes adjusting axis, using the colour aesthetic, and adding error bars)\",\"Using str_to_title function to convert string from ALL CAPS to Title Case\",\"Creating a Bland-Altman graph to explore relationship between sample size and median salary\",\"Using geom_text_repel function from ggrepel package to get text labels on scatter plot points\",\"Using count function's wt argument to specify what should be counted (default is number of rows)\",\"Spicing up a dull bar graph by adding a redundant colour aesthetic (trick from Julia Silge)\",\"Starting to explore relationship between gender and salary\",\"Creating a stacked bar graph (geom_col) of gender breakdown within majors\",\"Using summarise_at to aggregate men and women from majors into categories of majors\",\"Graphing scatterplot (geom_point) of share of women and median salary\",\"Using geom_smooth function to add a line of best fit to scatterplot above\",\"Explanation of why not to aggregate first when performing a statistical test (including explanation of Simpson's Paradox)\",\"Fixing geom_smooth so that we get one overall line while still being able to map to the colour aesthetic\",\"Predicting median salary from share of women with weighted linear regression (to take sample sizes into account)\",\"Using nest function and tidy function from the broom package to apply a linear model to many categories at once\",\"Using p.adjust function to adjust p-values to correct for multiple testing (using FDR, False Discovery Rate)\",\"Showing how to add an appendix to an RMarkdown file with code that doesn't run when compiled\",\"Using fct_lump function to aggregate major categories into the top four and an \\\"Other\\\" category\",\"Adding sample size to the size aesthetic within the aes function\",\"Using ggplotly function from plotly package to create an interactive scatterplot (tooltips appear when moused over)\",\"Exploring IQR (Inter-Quartile Range) of salaries by major\",\"Using parse_date function from lubridate package to convert date formatted as character to date class (should have used mdy function though)\",\"Using fct_lump function to aggregate distributors into top 6 (by number of movies) and and \\\"Other\\\" category\",\"Investigating strange numbers in the data and discovering duplication\",\"Using problems function to look at parsing errors when importing data\",\"Using arrange and distinct function and its .keep_all argument to de-duplicate observations\",\"Using geom_boxplot function to create a boxplot of budget by distributor\",\"Using floor function to bin release years into decades (e.g., \\\"1970\\\" and \\\"1973\\\" both become \\\"1970\\\")\",\"Using summarise_at function to apply the same function to multiple variables at the same time\",\"Using geom_line to visualize multiple metrics at the same time\",\"Using facet_wrap function to graph small multiples of genre-budget boxplots by distributor\",\"Starting analysis of profit ratio of movies\",\"Using paste0 function in a custom function to show labels of multiple (e.g., \\\"4X\\\" or \\\"6X\\\" to mean \\\"4 times\\\" or \\\"6 times\\\")\",\"Starting analysis of the most common genres over time\",\"Starting analysis of the most profitable individual horror movies\",\"Using paste0 function to add release date of movie to labels in a bar graph\",\"Using geom_text function, along with its check_overlap argument, to add labels to some points on a scatterplot\",\"Using ggplotly function from plotly package to create an interactive scatterplot\",\"Reviewing unexplored areas of investigation\",\"Using geom_line function to visualize changes over time\",\"Starting to decompose time series data into day-of-week trend and overall trend (lots of lubridate package functions)\",\"Using floor_date function from lubridate package to round dates down to the week level\",\"Using min function to drop incomplete/partial week at the start of the dataset\",\"Using countrycode function from countrycode package to replace two-letter country codes with full names (e.g., \\\"CA\\\" becomes \\\"Canada\\\")\",\"Using fct_lump function to get top N categories within a categorical variable and classify the rest as \\\"Other\\\"\",\"Using hour function from lubridate package to pull out integer hour value from a datetime variable\",\"Using facet_wrap function to graph small multiples of downloads by country, then changing scales argument to allow different scales on y-axis\",\"Starting analysis of downloads by IP address\",\"Using as.POSIXlt to combine separate date and time variables to get a single datetime variable\",\"Using lag function to calculate time between downloads (time between events) per IP address (comparable to SQL window function)\",\"Using as.numeric function to convert variable from a time interval object to a numeric variable (number in seconds)\",\"Explanation of a bimodal log-normal distribution\",\"Handy trick for setting easy-to-interpret intervals for time data on scale_x_log10 function's breaks argument\",\"Starting to explore package downloads\",\"Adding 1 to the numerator and denominator when calculating a ratio to get around dividing by zero\",\"Showing how to look at package download data over time using cran_downloads function from the cranlogs package\",\"Using count function to explore categorical variables\",\"Creating a quick-and-dirty map using geom_point function and latitude and longitude data\",\"Explaining need for mapproj package when plotting maps in ggplot2\",\"Using borders function to add US state borders to map\",\"Using fct_lump to get the top 6 project categories and put the rest in a lumped \\\"Other\\\" category\",\"Changing data so that certain categories' points appear in front of other categories' points on the map\",\"Taking the centroid (average longitude and latitude) of points across a geographic area as a way to aggregate categories to one point\",\"Using ifelse function to clean missing data that is coded as \\\"-9999\\\"\",\"Asking, \\\"How has turbine capacity changed over time?\\\"\",\"Exploring different models of wind turbines\",\"Using mutate_if function to find NA values (coded as -9999) in multiple columns and replace them with an actual NA\",\"Reviewing documentation for gganimate package\",\"Attempting to set up gganimate map\",\"Understanding gganimate package using a \\\"Hello World\\\" / toy example, then trying to debug turbine animation\",\"Using is.infinite function to get rid of troublesome Inf values\",\"Quick hack for getting cumulative data from a table using crossing function (though it does end up with some duplication)\",\"Diagnosis of gganimate issue (points between integer years are being interpolated)\",\"Pseudo-successful gganimate map (cumulative points show up, but some points are missing)\",\"Summary of screencast\",\"Importing data using the malariaAtlas package\",\"Using geom_line function to visualize malaria prevalence over time\",\"Quick map visualization using longitude and latitude coordinates and the geom_point function\",\"Using borders function to add Kenyan country borders to map\",\"Using scale_colour_gradient2 function to change the colour scale of points on the map\",\"Using arrange function to ensure that certain points on a map appear in front of/behind other points\",\"Aggregating data into decades using the truncated division operator %/%\",\"Starting to look at aggregated malaria data (instead of country-specific data)\",\"Using sample and unique functions to randomly select a few countries, which are then graphed\",\"Using last function to select the most recent observation from a set of arranged data\",\"Creating a Bland-Altman plot to explore relationship between current incidence and change in incidence in past 15 years\",\"Using anti_join function to find which countries are not in the malaria dataset\",\"Using the iso3166 dataset set in the maps package to match three-letter country code (i.e., the ISO 3166 code) with country names\",\"Creating a world map using geom_polygon function (and eventually theme_void and coord_map functions)\",\"Getting rid of Antarctica from world map\",\"Using facet_wrap function to create small multiples of world map for different time periods\",\"Starting to create an animated map of malaria deaths (actual code writing starts at 57:45)\",\"Starting with a single year after working through some bugs\",\"Using regex_inner_join function from the fuzzyjoin package to join map datasets because one of them has values in regular expressions\",\"As alternative to fuzzyjoin package in above step, using str_remove function to get rid of unwanted regex\",\"Starting to turn static map into an animation using gganimate package\",\"The actual animated map\",\"Using countrycode package to filter down to countries in a specific continent (Africa, in this case)\",\"Summary of screencast\",\"Exploratory bar chart of age distribution (and gender) of survey respondents\",\"Using count function on multiple columns to get detailed counts\",\"Parsing numbers from text using parse_number function, then using those numbers to re-level an ordinal factor (income bands)\",\"Exploring relationship between income and using homemade (vs. canned) cranberry sauce\",\"Adding group = 1 argument to the aes function to properly display a line chart\",\"Rotating text for axis labels that overlap\",\"Getting confidence intervals for proportions using Jeffreys interval (using beta distribution with an uniformative prior)\",\"Explanation of Clopper-Pearson approach as alternative to Jeffreys interval\",\"Using geom_ribbon function add shaded region to line chart that shows confidence intervals\",\"Using starts_with function to select fields with names that start with a certain string (e.g., using \\\"pie\\\" selects \\\"pie1\\\" and \\\"pie2\\\")\",\"Using gather function to get wide-format data to tidy (tall) format\",\"Using str_remove and regex to remove digits from field values (e.g., \\\"dessert1\\\" and \\\"dessert2\\\" get turned into \\\"dessert\\\")\",\"\\\"What are people eating?\\\" Graphing pies, sides, and desserts\",\"Using fct_reorder function to reorder foods based on how popular they are\",\"Using n_distinct function count the number of unique respondents\",\"Using facet_wrap function to facet food types into their own graphs\",\"Using parse_number function to convert age ranges as character string into a numeric field\",\"Exploring relationship between US region and food types\",\"Using group_by, then mutate, then count to calculate a complicated summary\",\"Exploring relationship between praying at Thanksgiving (yes/no) and food types\",\"Empirical Bayes binomial estimation for calculating binomial confidence intervals (see Dave's book on Empirical Bayes)\",\"Asking, \\\"What sides/desserts/pies are eaten together?\\\"\",\"Calculating pairwise correlation of food types\",\"Network graph of pairwise correlation\",\"Adding text labels to nodes using geom_node_text function\",\"Getting rid of unnecessary graph elements (e.g., axes, gridlines) with theme_void function\",\"Explanation of network graph relationships\",\"Adding dimension to network graph (node colour) to represent the type of food\",\"Fixing overlapping text labels using the geom_node_text function's repel argument\",\"Tweaking display of percentage legend to be in more readable format (e.g., \\\"40%\\\" instead of \\\"0.4\\\")\",\"Summary of screencast\",\"Using geom_line to create an exploratory line graph\",\"Using %/% operator (truncated division) to bin years into decades (e.g., 1980, 1984, and 1987 would all become \\\"1980\\\")\",\"Converting two-digit year to four-digit year (e.g., \\\"16\\\" becomes \\\"2016\\\") by adding 2000 to each one\",\"Using percent_format function from scales package to get nice-looking axis labels\",\"Using geom_col to create an ordered nice bar/column graph\",\"Using replace_na to replace NA values with \\\"Other\\\"\",\"Starting exploration of average daily traffic\",\"Using comma_format function from scales package to get more readable axis labels (e.g., \\\"1e+05\\\" becomes \\\"100,000\\\")\",\"Using cut function to bin continuous variable into customized breaks (also does a mutate within a group_by!)\",\"Starting to make a map\",\"Encoding a continuous variable to colour, then using scale_colour_gradient2 function to specify colours and midpoint\",\"Specifying the trans argument (transformation) of the scale_colour_gradient2 function to get a logarithmic scale\",\"Using str_to_title function to get values to Title Case (first letter of each word capitalized)\",\"Predicting whether bridges are in \\\"Good\\\" condition using logistic regression (remember to specify the family argument! Dave fixes this at 52:54)\",\"Explanation of why we should NOT be using an OLS linear regression\",\"Using the augment function from the broom package to illustrate why a linear model is not a good fit\",\"Specifying the type.predict argument in the augment function so that we get the actual predicted probability\",\"Explanation of why the sigmoidal shape of logistic regression can be a drawback\",\"Using a cubic spline model (a type of GAM, Generalized Additive Model) as an alternative to logistic regression\",\"Explanation of the shape that a cubic spline model can take (which logistic regression cannot)\",\"Visualizing the model in a different way, using a coefficient plot\",\"Using geom_vline function to add a red reference line to a graph\",\"Adding confidence intervals to the coefficient plot by specifying conf.int argument of tidy function and graphing using the geom_errorbarh function\",\"Brief explanation of log-odds coefficients\",\"Summary of screencast\",\"Using summarise_at and starts_with functions to quickly sum up all variables starting with \\\"tag_\\\"\",\"Using gather function (now pivot_longer) to convert topic tag variables from wide to tall (tidy) format\",\"Explanation of how gathering step above will let us find the most/least common tags\",\"Explanation of using median (instead of mean) as measure of central tendency for number of claps an article got\",\"Visualizing log-normal (ish) distribution of number of claps an article gets\",\"Using pmin function to bin reading times of 10 minutes or more to cap out at 10 minutes\",\"Changing scale_x_continuous function's breaks argument to get custom labels and tick marks on a histogram\",\"Discussion of using mean vs. median as measure of central tendency for reading time (he decides on mean)\",\"Starting text mining analysis\",\"Using unnest_tokens function from tidytext package to split character string into individual words\",\"Explanation of stop words and using anti_join function from tidytext package to get rid of them\",\"Using str_detect function to filter out \\\"words\\\" that are just numbers (e.g., \\\"2\\\", \\\"35\\\")\",\"Quick analysis of which individual words are associated with more/fewer claps (\\\"What are the hype words?\\\")\",\"Using geometric mean as alternative to median to get more distinction between words (note 27:33 where he makes a quick fix)\",\"Starting analysis of clusters of related words (e.g., \\\"neural\\\" is linked to \\\"network\\\")\",\"Finding correlations pairs of words using pairwise_cor function from widyr package\",\"Using ggraph and igraph packages to make network plot of correlated pairs of words\",\"Using geom_node_text to add labels for points (vertices) in the network plot\",\"Filtering original data to only include words appear in the network plot (150 word pairs with most correlation)\",\"Adding colour as a dimension to the network plot, representing geometric mean of claps\",\"Changing default colour scale to one with Blue = Low and High = Red with scale_colour_gradient2 function\",\"Adding dark outlines to points on network plot with a hack\",\"Starting to predict number of claps based on title tag (Lasso regression)\",\"Explanation of data format needed to conduct Lasso regression (and using cast_sparse function to get sparse matrix)\",\"Bringing in number of claps to the sparse matrix (un-tidy methods)\",\"Using cv.glmnet function (cv = cross validated) from glmnet package to run Lasso regression\",\"Finding and fixing mistake in defining Lasso model\",\"Explanation of Lasso model\",\"Using tidy function from the broom package to tidy up the Lasso model\",\"Visualizing how specific words affect the prediction of claps as lambda (Lasso's penalty parameter) changes\",\"Summary of screencast\",\"Using crossing function to set up structure of simulation (1,000 trials, each with 12 chess games)\",\"Adding result to the tidy simulation dataset\",\"Using sample function to simulate win/loss/draw for each game (good explanation of individual arguments within sample)\",\"Using group_by and summarise to get total points for each trial\",\"Adding red vertical reference line to histogram to know when a player wins a matchup\",\"Answering second piece of riddle (how many games would need to be played for better player to win 90% or 99% of the time?)\",\"Using unnest and seq_len function to create groups of number of games (20, 40, …, 100), each with one game per row\",\"Creating a win field based on the simulated data, then summarising win percentage for each group of number of games (20, 40, …, 100)\",\"Using seq function to create groups of number of games programmatically\",\"Explanation of using logarithmic scale for this riddle\",\"Changing spacing of number of games from even spacing (20, 40, …, 100) to exponential (doubles every time, 12, 24, 48, …, 1536)\",\"Changing spacing of number of games to be finer\",\"Introduction of interpolation as the last step we will do\",\"Introducing approx function as method to linearly interpolate data\",\"Break point for the next riddle\",\"Starting recursive approach to this riddle\",\"Setting up a N x N matrix (N = 4 to start)\",\"Explanation of approach (random ball goes into random cup, represented by matrix)\",\"Using sample function to pick a random element of the matrix\",\"Using for loop to iterate random selection 100 times\",\"Converting for loop to while loop, using colSums to keep track of number of balls in cups\",\"Starting to code the pruning phase\",\"Using diag function to pick matching matrix elements (e.g., the 4th row of the 4th column)\",\"Turning code up to this point into a custom simulate_round function\",\"Using custom simulate_round function to simulate 100 rounds\",\"Using all function to perform logic check on whether all cups in a round are not empty\",\"Converting loop approach to tidy approach\",\"Using rerun and map_lgl functions from purrr package to simulate a round for each for in a dataframe\",\"Explanation of the tidy approach\",\"Using cumsum and lag functions to keep track of the number of rounds until you win a \\\"game\\\"\",\"Creating histogram of number of rounds until winning a game\",\"Setting boundary argument of geom_histogram function to include count of zeros\",\"Brief explanation of geometric distribution\",\"Extending custom simulate_round function to include number of balls thrown to win (in addition to whether we won a round)\",\"Extending to two values of N (N = 3 or N = 4)\",\"Reviewing results of N = 3 and N = 4\",\"Extending to N = 5\",\"Checking results of chess riddle with Riddler solution\",\"Checking results of ball-cup riddle with Riddler solution (Dave slightly misinterpreted what the riddle was asking)\",\"Changing simulation code to correct the misinterpretation\",\"Reviewing results of corrected simulation\",\"Checking results of ball-cup riddle with corrected simulation with Riddler solutions\",\"Visualizing number of balls thrown and rounds played\",\"Separating column using separate function\",\"Taking distinct observation, but keeping the remaining variables using distinct function with .keep_all argument\",\"Using broom package and nest function to perform multiple t-tests at the same time\",\"Tidying nested t-test models using broom package\",\"Creating TIE fighter plot of estimates of means and their confidence intervals\",\"Recode long description using regex to remove everything after a parenthesis\",\"Using cut function to manually bin data along user-specified intervals\",\"Asking, \\\"What type of violations tend to occur more in some cuisines than others?\\\"\",\"Using semi_join function to get the most recent inspection of all the restaurants\",\"Asking, \\\"What violations tend to occur together?\\\"\",\"Using widyr package function pairwise_cor (pairwise correlation) to find co-occurrence of violation types\",\"Beginning of PCA (Principal Component Analysis) using widely_svd function\",\"Actually typing in the widely_svd function\",\"Reviewing and explaining output of widely_svd function\",\"Creating graph of opposing elements of a PCA dimension\",\"Shortening string using str_sub function\",\"Reference to Julia Silge's PCA walkthrough using StackOverflow data: https://juliasilge.com/blog/stack-overflow-pca/\",\"Using crossing function to get all combinations of specified variables (100 trials of 5 days)\",\"Using rbinom function to simulate whether it rains or not\",\"Using ifelse function to set starting number of umbrellas at beginning of week\",\"Explanation of structure of simulation and approach to determining number of umbrellas in each location\",\"Changing structure so that we have a row for each day's morning or evening\",\"Using group_by, ifelse, and row_number functions to set starting number of umbrellas for each trial\",\"Using case_when function to returns different values for multiple logical checks (allows for more outputs than ifelse)\",\"Using cumsum function to create a running tally of number of umbrellas in each location\",\"Explanation of output of simulated data\",\"Using any function to check if any day had a negative \\\"umbrella count\\\" (indicating there wasn't an umbrella available when raining)\",\"Asking, \\\"When was the first time Louie got wet?\\\"\",\"Creating a custom vector to convert an integer to a weekday (e.g., 2 = Tue)\",\"Using year function from lubridate package to simplify calculating age of dolphins\",\"Combining count and fct_lump functions to get counts of top 5 species (with other species lumped in \\\"Other\\\")\",\"Creating boxplot of species and age\",\"Dealing with different types of NA (double, logical) (he doesn't get it in this case, but it's still useful)\",\"Adding acquisition type as colour dimension to histogram\",\"Creating a spinogram of acquisition type over time (alternative to histogram) using geom_area\",\"Binning year into decade using truncated division operator %/%\",\"Fixing annoying triangular gaps in spinogram using complete function to fill in gaps in data\",\"Using fct_reorder function to reorder acquisition type (bigger categories are placed on the bottom of the spinogram)\",\"Adding vertical dashed reference line using geom_vline function\",\"Starting analysis of acquisition location\",\"Matching messy text data with regex to aggregate into a few categories variables with fuzzyjoin package\",\"Using distinct function's .keep_all argument to keep only one row per animal ID\",\"Using coalesce function to conditionally replace NAs (same functionality as SQL verb)\",\"Starting survival analysis\",\"Using survfit function from survival package to get a baseline survival curve (i.e., not regressed on any independent variables)\",\"Fixing cases where death year is before birth year\",\"Fixing specification of survfit model to better fit the format of our data (right-censored data)\",\"Built-in plot of baseline survival model (estimation of percentage survival at a given age)\",\"Using broom package to tidy the survival model data (which is better for ggplot2 plotting)\",\"Fitting survival curve based on sex\",\"Cox proportional hazards model (to investigate association of survival time and one or more predictors)\",\"Explanation of why dolphins with unknown sex likely have a systematic bias with their data\",\"Investigating whether being born in captivity is associated with different survival rates\",\"Summary of screencast\",\"Importing an rds file using read_rds function\",\"Using floor_date function from lubridate package to round dates down (that's what the floor part does) to the month level\",\"Asking, \\\"Which tweets get the most re-tweets?\\\"\",\"Using contains function to select only columns that contain a certain string (\\\"retweet\\\" in this case)\",\"Exploring likes/re-tweets ratio, including dealing with one or the other being 0 (which would cause divide by zero error)\",\"Starting exploration of actual text of tweets\",\"Using unnest_tokens function from tidytext package to break tweets into individual words (using token argument specifically for tweet-style text)\",\"Using anti_join function to filter out stop words (e.g., \\\"and\\\", \\\"or\\\", \\\"the\\\") from tokenized data frame\",\"Calculating summary statistics per word (average retweets and likes), then looking at distributions\",\"Explanation of Poisson log normal distribution (number of retweets fits this distribution)\",\"Additional example of Poisson log normal distribution (number of likes)\",\"Explanation of geometric mean as better summary statistic than median or arithmetic mean\",\"Using floor_date function from lubridate package to floor dates to the week level and tweaking so that a week starts on Monday (default is Sunday)\",\"Asking, \\\"What topic is each week about?\\\" using just the tweet text\",\"Calculating TF-IDF of tweets, with week as the \\\"document\\\"\",\"Using top_n and group_by functions to select the top tf-idf score for each week\",\"Using str_detect function to filter out \\\"words\\\" that are just numbers (e.g., 16, 36)\",\"Using distinct function with .keep_all argument to ensure only top 1 result, as alternative to top_n function (which includes ties)\",\"Making Jenny Bryan disappointed\",\"Using geom_text function to add text labels to graph to show to word associated with each week\",\"Using geom_text_repel function from ggrepel package as an alternative to geom_text function for adding text labels to graph\",\"Using rvest package to scrape web data from a table in Tidy Tuesday README\",\"Starting to look at #rstats tweets\",\"Spotting signs of fake accounts with purchased followers (lots of hashtags)\",\"Explanation of spotting fake accounts\",\"Using str_detect to filter out web URLs\",\"Using str_count function and some regex to count how many hashtags a tweet has\",\"Creating a Bland-Altman plot (total on x-axis, variable of interest on y-axis)\",\"Using geom_text function with check_overlap argument to add labels to scatterplot\",\"Asking, \\\"Who are the most active #rstats tweeters?\\\"\",\"Summary of screncast\",\"Quick tip on how to start exploring a new dataset\",\"Investigating inconsistency of shows having a count of seasons that is different from the number of seasons given in the data\",\"Using %in% operator and all function to only get shows that have a first season and don't have skipped seasons in the data\",\"Asking, \\\"Which seasons have the most variation in ratings?\\\"\",\"Using facet_wrap function to separate different shows on a line graph into multiple small graphs\",\"Writing custom embedded function to get width of breaks on the x-axis to always be even (e.g., season 2, 4, 6, etc.)\",\"Committing, finding, and explaining a common error of using the same variable name when summarizing multiple things\",\"Using truncated division operator %/% to bin data into two-year bins instead of annual (e.g., 1990 and 1991 get binned to 1990)\",\"Using subsetting (with square brackets) within the mutate function to calculate mean on only a subset of data (without needing to filter)\",\"Using gather function (now pivot_longer) to get metrics as columns into tidy format, in order to graph them all at once with a facet_wrap\",\"Using pmin function to lump all seasons after 4 into one row (it still shows \\\"4\\\", but it represents \\\"4+\\\")\",\"Asking, \\\"If season 1 is good, do you get a second season?\\\" (show survival)\",\"Using paste0 and spread functions to get season 1-3 ratings into three columns, one for each season\",\"Using distinct function with .keep_all argument remove duplicates by only keeping the first one that appears\",\"Using logistic regression to answer, \\\"Does season 1 rating affect the probability of getting a second season?\\\" (note he forgets to specify the family argument, fixed at 57:25)\",\"Using ntile function to divide data into N bins (5 in this case), then eventually using cut function instead\",\"Adding year as an independent variable to the logistic regression model\",\"Adding an interaction term (season 1 interacting with year) to the logistic regression model\",\"Using augment function as a method of visualizing and interpreting coefficients of regression model\",\"Using crossing function to create new data to test the logistic regression model on and interpret model coefficients\",\"Fitting natural splines using the splines package, which would capture a non-linear relationship\",\"Summary of screencast\",\"Using str_detect function to find missions with \\\"Apollo\\\" in their name\",\"Starting EDA (exploratory data analysis)\",\"Using fct_collapse function to recode factors (similar to case_when function)\",\"Using countrycode function from countrycode package to get full country names from country codes (e.g. \\\"RU\\\" becomes \\\"Russia\\\")\",\"Using replace_na function to convert NA (missing) observations to \\\"Other\\\"\",\"Creating a line graph using geom_line function with different colours for different categories\",\"Using fct_reorder function to reorder factors in line graph above, in order to make legend more readable\",\"Creating a bar graph, using geom_col function, of most active (by number of launches) private or startup agencies\",\"Using truncated division operator %/% to bin data into decades\",\"Using complete function to turn implicit zeros into explicit zeros (makes for a cleaner line graph)\",\"Using facet_wrap function to create small multiples of a line graph, then proceeding to tweak the graph\",\"Using semi_join function as a filtering step\",\"Using geom_point to create a timeline of launches by vehicle type\",\"Explanation of why boxplots over time might not be a good visualization choice\",\"Using geom_jitter function to tweak the timeline graph to be more readable\",\"Creating a second timeline graph for US vehicles and launches\",\"Summary of screencast\",\"Creating a facetted (small multiples) line graph of incarceration rate by urbanicity and race over time\",\"Discussion of statistical testing of incarceration rates by urbanicity (e.g., rural, suburban)\",\"Exploring the extent of missing data on prison population\",\"Using any function to filter down to states that have at least one (hence the any function) row of non-missing data\",\"Using cut function to manually bin data along user-specified intervals\",\"Starting to create a choropleth map of incarceration rate by state\",\"Using match function to match two-letter state abbreviation to full state name, in order to get data needed to create a map\",\"Actually typing the code (now that we have the necessary data) to create a choropleth map\",\"Using str_remove function and regex to chop off the end of county names (e.g., \\\"Allen Parish\\\" becomes \\\"Allen\\\")\",\"Making choropleth more specific by drilling down to county-level data\",\"Starting to make an animated choropleth map using gganimate\",\"Using modulo operator %% to choose every 5th year\",\"Using scale_fill_gradient2 function's limits argument to exclude unusally high values that were blowing out the scale\",\"Using summarise_at function to apply the same function to multiple fields at the same time\",\"Starting to investigate missing data (how much is missing, where is it missing, etc.)\",\"Creating a line graph that excludes counties with missing data\",\"Summary of screencast\",\"Identifying the need for a gather step\",\"Changing snake case to title case using str_to_title and str_replace_all functions\",\"Identifying need for separating categories into major and minor categories (e.g., \\\"Cheese Other\\\" can be divided into \\\"Cheese\\\" and \\\"Other\\\")\",\"Using separate function to split categories into major and minor categories (good explanation of \\\"extra\\\" argument, which merges additional separations into one field)\",\"Using coalesce function to deal with NAs resulting from above step\",\"Dealing with graph of minor category that is linked to multiple major categories (\\\"Other\\\" linked to \\\"Cheese\\\" and \\\"Frozen\\\")\",\"Introducing fct_lump function as an approach to work with many categories\",\"Introducing facetting (facet_wrap function) as second alternative to working with many categories\",\"Dealing with \\\"Other\\\" category having two parts to it by using ifelse function in the cleaning step (e.g., go from \\\"Other\\\" to \\\"Other Cheese\\\")\",\"Looking at page for the sweep package\",\"Using tk_ts function to coerce a tibble to a timeseries\",\"Turning year column (numeric) into a date by adding number of years to Jan 1, 0001\",\"Nesting time series object into each combination of category and product\",\"Applying ETS (Error, Trend, Seasonal) model to each time series\",\"Using sw_glance function (sweep package's version of glance function) to pull out model parameters from model field created in above step\",\"Using sw_augment function to append fitted values and residuals from the model to the original data\",\"Visualising actual and fitted values on the same graph to get a look at the ETS model\",\"Using Arima function (note the capital A) as alternative to ETS (not sure what difference is between arima and Arima)\",\"Forecasting into the future using an ETS model using various functions: unnest, sw_sweep, forecast\",\"Using geom_ribbon function to add confidence bounds to forecast\",\"Forecasting using auto-ARIMA (instead of ETS)\",\"Applying two forecasting methods at the same time (auto-ARIMA and ETS) using the crossing function\",\"Quick test of how invoke function works (used to call a function easily, e.g., when it is a character string instead of called directly)\",\"Removing only one part of legend (line type of solid or dashed) using scale_linetype_discrete function\",\"Using gather function to clean up new dataset\",\"Using fct_recode to fix a typo in a categorical variable\",\"Copy-pasting previous forecasting code to cheese and reviewing any changes needed\",\"Discussing alternative approach: creating interactive visualisation using shiny package to do direct comparisons\",\"Using read_xlsx function to read in Excel spreadsheet, including skipping first few rows that don't have data\",\"Overview of starting very messy data\",\"Using gather function to clean up wide dataset\",\"Using fill function to fill in NA values with a entries in a previous observation\",\"Cleaning variable that has number and percent in it, on top of one another using a combination of ifelse and fill functions\",\"Using spread function on cleaned data to separate number and percent by year\",\"Spotted a mistake where he had the wrong string on str_detect function\",\"Using sample function to get 6 random fields of study to graph\",\"Cleaning another dataset, which is much easier to clean\",\"Renaming the first field, even without knowing the exact name\",\"Cleaning another dataset\",\"Discussing challenge of when indentation is used in original dataset (for group / sub-group distinction)\",\"Starting to separate out data that is appended to one another in the original dataset (all, male, female)\",\"Removing field with long name using contains function\",\"Using fct_recode function to rename an oddly-named category in a categorical variable (ifelse function is probably a better alternative)\",\"Discussing solution to broad major field description and fine major field description (meaningfully indented in original data)\",\"Using setdiff function to separate broad and fine major fields\",\"Boxplots of departure stations using fct_lump function\",\"Creating heat map of departure and arrival delays, then cleaning up a sparse heat map\",\"Using fct_reorder function and length function to reorder stations based on how frequently they appear\",\"Using fct_infreq to reorder based on infrequently-appearing stations (same as above, but without a trick needed)\",\"Using fct_lump function to lump based on proportion instead of number of top categories desired\",\"Using scale_fill_gradient2 function to specify diverging colour scale\",\"Checking another person's take on the data, which is a heatmap over time\",\"Converting year and month (as digits) into date-class variable using sprintf function and padding month number with extra zero when necessary\",\"Using summarise_at function to quickly sum multiple columns\",\"Creating heatmap using geom_tile function for percentage of late trains by station over time\",\"Using fill function to fill in missing NA values with data from previous observations\",\"Grouping multiple variables into a single category using paste0 function\",\"Grouping heatmap into International / National chunks with a weird hack\",\"Further separating International / National visually\",\"Less hacky way of separating International / National (compared to previous two rows)\",\"Writing a custom function that summarizes variables based on their names (then abandoning the idea)\",\"Using complete.cases function to find observations that have an NA value in any variable\",\"Using subsetting within a summarise function to calculate a weighted mean when dealing with 0 or NA values in some observations\",\"Debugging what is causing NA values to appear in the summarise output (finds the error at 13:25)\",\"Hypothesizing about one sector illustrating a variation of Simpson's Paradox\",\"Creating a scatterplot with a logarithmic scale and using scale_colour_gradient2 function to encode data to point colour\",\"Creating an interactive plot (tooltips show up on hover) using ggplotly function from plotly package\",\"Fiddling with scale_size_continuous function's range argument to specify point size on a scatterplot (which are encoded to total workers)\",\"Explanation of why healthcare sector is a good example of Simpson's Paradox\",\"Starting to create a shiny app with \\\"occupation\\\" as only input (many tweaks in subsequent minutes to make it work)\",\"Tweaking size (height) of graph in shiny app\",\"Summary of screencast\",\"Starting EDA (exploratory data analysis) with counts of categorical variables\",\"Specifying scale_x_log10 function's breaks argument to get sensisble tick marks for time on histogram\",\"Tweaking geom_histogram function's binwidth argument to get something that makes sense for log scale\",\"Using separate_rows to break down comma-separated values for three different categorical variables\",\"Using top_n to get top 20 observations from each of several categories (not quite right, fixed at 17:47)\",\"Troubleshooting various issues with facetted graph (e.g., ordering, values appearing in multiple categories)\",\"Starting prediction of average rating with a linear model\",\"Splitting data into train/test sets (training/holdout)\",\"Investigating relationship between max number of players and average rating (to determine if it should be in linear model)\",\"Exploring average rating over time (\\\"Do newer games tend to be rated higher/lower?\\\")\",\"Discussing necessity of controlling for year a game was published in the linear model\",\"Non-model approach to exploring relationship between game features (e.g., card game, made in Germany) on average rating\",\"Using geom_boxplot function to create boxplot of average ratings for most common game features\",\"Using unite function to combine multiple variables into one\",\"Introducing Lasso regression as good option when you have many features likely to be correlated with one another\",\"Writing code to set up Lasso regression using glmnet and tidytext packages\",\"Adding average rating to the feature matrix (warning: method is messy)\",\"Using setdiff function to find games that are in one set, but not in another (while setting up matrix for Lasso regression)\",\"Spotting the error stemming from the step above (calling row names from the wrong data)\",\"Explaining what a Lasso regression does, including the penalty parameter lambda\",\"Using a cross-validated Lasso model to choose the level of the penalty parameter (lambda)\",\"Adding non-categorical variables to the Lasso model to control for them (e.g., max number of players)\",\"Using unite function to combine multiple variables into one, separated by a colon\",\"Graphing the top 20 coefficients in the Lasso model that have the biggest effect on predicted average rating\",\"Mentioning the yardstick package as a way to evaluate the model's performance\",\"Discussing drawbacks of linear models like Lasso (can't do non-linear relationships or interaction effects)\",\"Using mdy function from lubridate package to convert character-formatted date to date-class\",\"Exploratory bar graph showing top species of cats, using geom_col function\",\"Specifying facet_wrap function's ncol argument to get graphs stacked vertically (instead of side-by-side)\",\"Asking, \\\"Are some animal names associated with particular dog breeds?\\\"\",\"Explanation of add_count function\",\"Adding up various metrics (e.g., number of names overall, number of breeds overall), but note a mistake that gets fixed at 17:05\",\"Calculating a ratio for names that appear over-represented within a breed, then explaining how small samples can be misleading\",\"Spotting and fixing an aggregation mistake\",\"Explanation of how to investigate which names might be over-represented within a breed\",\"Explanation of how to use hypergeometric distribution to test for name over-representation\",\"Using phyper function to calculate p-values for a one-sided hypergeometric test\",\"Additional explanation of hypergeometric distribution\",\"First investigation of why and how to interpret a p-value histogram (second at 29:45, third at 37:45, and answer at 39:30)\",\"Noticing that we are missing zeros (i.e., having a breed/name combination with 0 dogs), which is important for the hypergeometric test\",\"Using complete function to turn implicit zeros (for breed/name combination) into explicit zeros\",\"Second investigation of p-value histogram (after adding in implicit zeros)\",\"Explanation of multiple hypothesis testing and correction methods (e.g., Bonferroni, Holm), and applying using p.adjust function\",\"Explanation of False Discovery Rate (FDR) control as a method for correcting for multiple hypothesis testing, and applying using p.adjust function\",\"Third investigation of p-value histogram, to hunt for under-represented names\",\"Answer to why the p-value distribution is not well-behaved\",\"Using crossing function to created a simulated dataset to explore how different values affect the p-value\",\"Explanation of how total number of names and total number of breeds affects p-value\",\"More general explanation of what different shapes of p-value histogram might indicate\",\"Renaming variables within a transmute function, using backticks to get names with spaces in them\",\"Using kable function from the knitr package to create a nice-looking table\",\"Explanation of one-side p-value (as opposed to two-sided p-value)\",\"Summary of screencast\",\"Using summarise_all / summarise_at function to aggregate multiple variables at the same time\",\"Using magnitude instead of absolute numbers to see trends in time of day\",\"Dividing time into categories (four categories for times of day, e.g., morning commute, night) using between function\",\"Looking for systematically missing data (which would bias the results of the analysis)\",\"Summarising using a filter in the arguments based on whether the time window is during a commute time\",\"Combining day of week and hour using functions in the lubridate package and as.difftime function (but then he uses facetting as an easier method)\",\"Normalizing day of week data to percent of weekly traffic\",\"Starting analysis of directions of travel by time of day (commute vs. reverse-commute)\",\"Filtering out weekend days using wday function from lubridate package\",\"Using spread function to create new variable of ratio of bike counts at different commute times\",\"Visualizing ratio of bike counts by time of day\",\"Visualizing ratio by hour instead of time of day\",\"Ordering crossing in graph by when the average trip happened using mean of hour weighted by bike count\",\"Quick and dirty filter when creating a new variable within a mutate function\",\"Identifying duplicated rows ands fixing them\",\"Using add_count and fct_reorder functions to order categories that are broken down into sub-categories for graphing\",\"Tidying graph titles (e.g., replacing underscores with spaces) using str_to_title and str_replace functions\",\"Using inner_join function to merge datasets\",\"Calculating age from date of birth using difftime and as.numeric functions\",\"Adding simple calculations like mean and median into the text portion of markdown document\",\"Looking at distribution of wins by sex using overlapping histograms\",\"Binning years into decades using truncated division %/%\",\"Splitting up boxplots so that they are separated into pairs (M/F) across a different group (decade) using interaction function\",\"Analyzing distribution of ages across decades, looking specifically at the effect of Serena Williams (one individual having a disproportionate affect on the data, making it look like there's a trend)\",\"Avoiding double-counting of individuals by counting their average age instead of their age at each win\",\"Starting analysis to predict winner of Grand Slam tournaments\",\"Creating rolling count using row_number function to make a count of previous tournament experience\",\"Creating rolling win count using cumsum function\",\"Lagging rolling win count using lag function (otherwise we get information about a win before a player has actually won, for prediction purposes)\",\"Asking, \\\"When someone is a finalist, what is their probability of winning as a function of previous tournaments won?\\\"\",\"Asking, \\\"How does the number of wins a finalist has affect their chance of winning?\\\"\",\"Backtesting simple classifier where person with more tournament wins is predicted to win the given tournament\",\"Creating classifier that gives points based on how far a player got in previous tournaments\",\"Using match function to turn name of round reached (1st round, 2nd round, …) into a number score (1, 2, …)\",\"Using cummean function to get score of average past performance (instead of cumsum function)\",\"Pulling names of rounds (1st round, 2nd round, … ) based on the rounded numeric score of previous performance\",\"Analyzing when NAs appear in a dimension\",\"Looking at multiple categorical variable at the same time by gathering them into one column and eventually graphing each as a different facet\",\"Re-order facet graphs according to which ones have the fewest categories in them to ones that have the most\",\"Geometric mean for estimating counts when there are a lot of low values (1-3 bird collisions, in this case)\",\"Filling in \\\"blank\\\" observations where there were no observations made\",\"Using log+1 to convert a dimension with values of 0 into a log scale\",\"Adding confidence bounds for data using a geometric mean (where he first gets the idea of bootstrapping)\",\"Actual coding of bootstrap starts\",\"Adding confidence bounds using bootstrap data\",\"Investigating potential confounding variables\",\"Discussing approaches to dealing with confounding variables\",\"Using complete function to get explicit NA values\",\"Using slice function to select 10 highest and 10 lowest student-teacher ratios (like a filter using row numbers)\",\"Adding GDP per capita to a dataset using WDI package\",\"Using geom_text to add labels to points on a scatterplot\",\"Using WDIsearch function from WDI package to search for country population data\",\"Explanation of trick with geom_text function's check_overlap argument to get label for US to appear by rearranging row order\",\"Using comma_format function from scales format to get more readable numeric legend (e.g., \\\"500,000,000\\\" instead of \\\"5e+08\\\")\",\"Exploring different education-related indicators in the WDI package\",\"Using spread function (now pivot_wider) to turn data from tidy to wide format\",\"Using to_snake_case function from snakecase package to conver field names to snake_case\",\"Exploring female/male school secondary school enrollment\",\"Note of caution on keeping confounders in mind when interpreting scatterplots\",\"Creating a linear regression of secondary school enrollment to explore confounders\",\"Discussing the actual confounder (GDP per capita) in the linear regression above\",\"Adding world region as another potential confounder\",\"Using aov function (ANOVA) to explore confounders further\",\"Reviewing and interpreting the final linear regression model\",\"Using cor function (correlation) to get correlation matrix for three variables (and brief explanation of multi-collinearity)\",\"Summary of screencast\",\"Creating a stacked bar plot using geom_col and the aes function's fill argument (also bins years into decades with truncated division operator %/%)\",\"Using n_distinct function to quickly count unique years in a group\",\"Using distinct function and its .keep_all argument to de-duplicate data\",\"Using coalesce function to replace NAs in a variable (similar to SQL COALESCE verb)\",\"Using year function from lubridate package to calculate (approx.) age of laureates at time of award\",\"Using fct_reorder function to arrange boxplot graph by the median age of winners\",\"Defining a new variable within the count function (like doing a mutate in the count function)\",\"Creating a small multiples bar plot using geom_col and facet_wrap functions\",\"Importing income data from WDI package to explore relationship between high/low income countries and winners\",\"Using fct_relevel to change the levels of a categorical income variable (e.g., \\\"Upper middle income\\\") so that the ordering makes sense\",\"Starting to explore new dataset of nobel laureate publications\",\"Taking the mean of a subset of data without needing to fully filter the data beforehand\",\"Using rank function and its ties.method argument to add the ordinal number of a laureate's publication (e.g., 1st paper, 2nd paper)\",\"Lots of playing around with exploratory histograms (geom_histogram)\",\"Discussion of right-censoring as an issue (people winning the Nobel prize but still having active careers)\",\"Summary of screencast\",\"Using summarise_all to get proportion of NA values across many variables\",\"Adding text labels to scatter plot for some points using check_overlap argument\",\"Using pmin function to get the lower of two possible numbers for a percentage variable that was showing > 100%\",\"Starting to make a choropleth map\",\"Connecting ISO country names (used in mapping code) to country names given in the dataset\",\"Actual code to create the map using given longitude and latitude\",\"Using fuzzyjoin package to link variables that use regular expression instead of character (using regex_right_join / regex_left_join function)\",\"Using coord_fixed function as a hack to get proper ratios for maps\",\"Bringing in additional data using WDI package\",\"Using patchwork package to show multiple graphs in the same plot\",\"Importing and rename multiple indicators from the WDI package at the same time\",\"Using extract function from tidyr package to pull out year from text field\",\"Changing extract function to pull out year column more accurately\",\"Starting to explore prediction of points\",\"Using fct_lump on country variable to collapse countries into an \\\"Other\\\" category, then fct_relevel to set the baseline category for a linear model\",\"Investigating year as a potential confounding variable\",\"Investigating \\\"taster_name\\\" as a potential confounding variable\",\"Coefficient (TIE fighter) plot to see effect size of terms in a linear model, using tidy function from broom package\",\"Polishing category names for presentation in graph using str_replace function\",\"Using augment function to add predictions of linear model to original data\",\"Plotting predicted points vs. actual points\",\"Using ANOVA to determine the amount of variation that explained by different terms\",\"Using tidytext package to set up wine review text for Lasso regression\",\"Setting up and using pairwise_cor function to look at words that appear in reviews together\",\"Creating sparse matrix using cast_sparse function from tidytext package; used to perform a regression on positive/negative words\",\"Checking if rownames of sparse matrix correspond to the wine_id values they represent\",\"Setting up sparse matrix for using glmnet package to do sparse regression using Lasso method\",\"Actually writing code for doing Lasso regression\",\"Basic explanation of Lasso regression\",\"Putting Lasso model into tidy format\",\"Explaining how the number of terms increases as lambda (penalty parameter) decreases\",\"Answering how we choose a lambda value (penalty parameter) for Lasso regression\",\"Using parallelization for intensive computations\",\"Adding price (from original linear model) to Lasso regression\",\"Shows glmnet.fit piece of a Lasso (glmnet) model\",\"Picking a lambda value (penalty parameter) and explaining which one to pick\",\"Taking most extreme coefficients (positive and negative) by grouping theme by direction\",\"Demonstrating tidytext package's sentiment lexicon, then looking at individual reviews to demonstrate the model\",\"Visualizing each coefficient's effect on a single review\",\"Using str_trunc to truncate character strings\",\"Looking at the website the data came from\",\"Using gather function (now pivot_longer) to convert wide data to long (tidy) format\",\"Graphing counts of all categorical variables at once, then exploring them\",\"Using fct_lump function to lump three categorical variables to the top N categories and \\\"Other\\\"\",\"Using reorder_within function to re-order factors that have the same name across multiple facets\",\"Using lm function (linear model) to predict star rating\",\"Visualising effects (and 95% CI) of indendent variables in linear model with a coefficient plot (TIE fighter plot)\",\"Using fct_relevel function to get \\\"Other\\\" as the base reference level for categorical independent variables in a linear model\",\"Using extract function and regex to split a camelCase variable into two separate variables\",\"Using facet_wrap function to split coefficient / TIE fighter plot into three separate plots, based on type of coefficient\",\"Using geom_vline function to add reference line to graph\",\"Using unnest_tokens function from tidytext package to explore the relationship between variety (a sparse categorical variable) and star rating\",\"Explanation of how he would approach variety variable with Lasso regression\",\"Web scraping the using rvest package and SelectorGadget (Chrome Extension CSS selector)\",\"Actually writing code for web scraping, using read_html, html_node, and html_table functions\",\"Using clean_names function from janitor package to clean up names of variables\",\"Explanation of web scraping task: get full review text using the links from the review summary table scraped above\",\"Using parse_number function as alternative to as.integer function to cleverly drop extra weird text in review number\",\"Using SelectorGadget (Chrome Extension CSS selector) to identify part of page that contains review text\",\"Using html_nodes, html_text, and str_subset functions to write custom function to scrape review text identified in step above\",\"Adding message function to custom scraping function to display URLs as they are being scraped\",\"Using unnest_tokens and anti_join functions to split review text into individual words and remove stop words (e.g., \\\"the\\\", \\\"or\\\", \\\"and\\\")\",\"Catching a mistake in the custom function causing it to read the same URL every time\",\"Using str_detect function to filter out review paragraphs without a keyword in it\",\"Using str_remove function and regex to get rid of string that follows a specific pattern\",\"Explanation of possibly and safely functions in purrr package\",\"Reviewing output of the URL that failed to scrape, including using character(0) as a default null value\",\"Using pairwise_cor function from widyr package to see which words tend to appear in reviews together\",\"Using igraph and ggraph packages to make network plot of word correlations\",\"Using geom_node_text function to add labels to network plot\",\"Including all words (not just those connected to others) as vertices in the network plot\",\"Tweaking and refining network plot aesthetics (vertex size and colour)\",\"Weird hack for getting a dark outline on hard-to-see vertex points\",\"Summary of screencast\",\"Explaining use of semi_join function to aggregate and filter groups\",\"Putting the largest categories on the bottom of a stacked bar chart\",\"Using glue function as alternative to paste for combining text, plus good explanation of it\",\"Multiple re-ordering using fct_reorder function of facetted graph (he works through several obstacles)\",\"Re-ordering the position of facetted graphs so that highest total revenue is at top left\",\"Investigating relationship between year created and revenue\",\"Creating scatter plot with points scaled by size and labelled points (geom_text function)\",\"Summary of screencast up to this point\",\"Starting analysis original media of franchise (e.g., novel, video game, animated film) and revenue type (e.g., box office, merchandise)\",\"Graphing original media and revenue category as facetted bar plot with lots of reordering (ends at around 38:40)\",\"Alternative visualization of original media/revenue category using heat map\",\"Using scale_fill_gradient2 function to specify custom colour scale\",\"Getting rid of gridlines in graph using theme function's panel.grid argument\",\"Using fct_rev function to reverse levels of factors\",\"Fixing overlapping axis text with tweaks to theme function's axis.text argument\",\"Reviewing visualization that inspired this dataset\",\"Adding text of total revenue to the end of each bar in a previous graph\",\"Using paste0 function at add a \\\"B\\\" (for \\\"billions\\\") to the end of text labels on graph\",\"Using expand_limits functions to give more space for text labels not to get cut off\",\"Summary of screencast\",\"Adding country names using countrycode package\",\"Web scraping country codes from Wikipedia\",\"Combining tables that are separate lists into one dataframe\",\"Using rev function (reverse) to turn multiple rows of soccer match scores into one row (base team and opposing team)\",\"Applying a geom_smooth linear model line to a scatter plot, then facetting it\",\"Adding a line with a slope of 1 (x = y) using geom_abline\",\"Pulling out elements of a list that is embedded in a dataframe\",\"Using glue function to add context to facet titles\",\"Using clean_names function in janitor package to get field names to snake_case\",\"Using gather function to get wide elements into tall (tidy) format\",\"Cleaning text (str_to_title, str_replace) to get into nicer-to-read format\",\"Using str_remove_all function to trim trimming quotation marks and backslashes\",\"Using extract function to extract the season number and episode number from episode field; uses regex capturing groups\",\"Using add_count function's name argument to specify field's name\",\"Getting into whether the elements of Ross's paintings changed over time (e.g., are mountains more/less common over time?)\",\"Quick point: could have used logistic regression to see change over time of elements\",\"Asking, \\\"What elements tends to appear together?\\\" prompting clustering analysis\",\"Using pairwise_cor to see which elements tend to appear together\",\"Discussion of a blind spot of pairwise correlation (high or perfect correlation on elements that only appear once or twice)\",\"Asking, \\\"What are clusters of elements that belong together?\\\"\",\"Creating network plot using ggraph and igraph packages\",\"Reviewing network plot for interesting clusters (e.g., beach cluster, mountain cluster, structure cluster)\",\"Explanation of Principal Component Analysis (PCA)\",\"Start of actual PCA coding\",\"Using acast function to create matrix of painting titles x painting elements (initially wrong, corrected at 36:30)\",\"Centering the matrix data using t function (transpose of matrix), colSums function, and colMeans function\",\"Using svd function to performn singular value decomposition, then tidying with broom package\",\"Exploring one principal component to get a better feel for what PCA is doing\",\"Using reorder_within function to re-order factors within a grouping\",\"Exploring different matrix names in PCA (u, v, d)\",\"Looking at top 6 principal components of painting elements\",\"Showing percentage of variation that each principal component is responsible for\",\"Using str_detect function to find guests that played themselves\",\"Using separate_rows function and regex to get delimited values onto different rows (e.g., \\\"Edna Krabappel; Ms. Melon\\\" gets split into two rows)\",\"Using parse_number function to convert a numeric variable coded as character to a proper numeric variable\",\"Downloading and importing supplementary dataset of dialogue\",\"Using semi_join function to filter dataframe based on values that appear in another dataframe\",\"Using anti_join function to check which values in a dataframe do not appear in another dataframe\",\"Using ifelse function to recode a single value with another (i.e., \\\"Edna Krapabbel\\\" becomes \\\"Edna Krabappel-Flanders\\\")\",\"Explaining the goal of all the data cleaning steps\",\"Using sample function to get an example line for each character\",\"Setting geom_histogram function's binwidth and center arguments to get specific bin sizes\",\"Using unnest_tokens and anti_join functions from tidytext package to split dialogue into individual words and remove stop words (e.g., \\\"the\\\", \\\"or\\\", \\\"and\\\")\",\"Using bind_tf_idf function from tidytext package to get the TF-IDF (term frequency-inverse document frequency) of individual words\",\"Using top_n function to get the top 1 TF-IDF value for each role\",\"Using paste0 function to combine two character variables (e.g., \\\"Groundskeeper Willie\\\" and \\\"ach\\\" (separate variables) become \\\"Groundskeeper Willie: ach\\\")\",\"Explanation of what TF-IDF (text frequency-inverse document frequency) tells us and how it is a \\\"catchphrase detector\\\"\",\"Summary of screencast\",\"Transforming time into something more readable (from time value of seconds since Unix epoch [1970-01-01] ), then converting it into a date\",\"Formatting x-axis text so that it is rotated and readable, then re-ordering using fct_relevel function so that it is in its proper ordinal order\",\"Converting string answers to integer counterparts to get an overall numeric value for how good each place is\",\"Commentary on speed of mutate calculation within or without a group (non-grouped is slightly faster)\",\"Re-ordering groups by total votes using fct_reorder function, while still maintaining the groups themselves\",\"Using glue package to combine place name and total respondents\",\"Using statistical test to give confidence intervals on average score\",\"Actually using the t.test function with toy example\",\"Using weighted linear model instead (which doesn't end up working)\",\"Using custom function with rep function to get vector of repeated scores (sneaky way of weighting) so that we can perform a proper t-test\",\"Summarizing t-test function into a list (alternative to nesting)\",\"Adding error bars using geom_errorbarh to make a TIE fighter plot that shows confidence intervals\",\"Bringing in additional data from Barstool ratings (to supplement survey of Open R meetup NY)\",\"Getting survey data to the place level so that we can add an additional dataset\",\"Checking for duplicates in the joined data\",\"Calling off the planned analysis due to low sample sizes (too much noise, not enough overlap between datasets)\",\"Looking at Barstool data on its own\",\"Renaming all variables with a certain string pattern in them\",\"Comparing Dave's reviews with all other critics\",\"Adding geom_abline showing x = y as comparison for geom_smooth linear model line\",\"Changing the location of the aes() to change what the legend icons look like for size aesthetic\",\"Using select and sort and colnames functions to sort variables in alphabetical order\",\"Adding geom_abline for y = x to a scatter plot for comparison\",\"Visualising using geom_boxplot for mpg by vehicle class (size of car)\",\"Start of explanation of prediction goals\",\"Creating train and test sets, along with trick using sample_frac function to randomly re-arrange all rows in a dataset\",\"First step of developing linear model: visually adding geom_smooth\",\"Using augment function to add extra variables from model to original dataset (fitted values and residuals, especially)\",\"Creating residuals plot and explaining what you want and don't want to see\",\"Explanation of splines\",\"Visualising effect of regressing using natural splines\",\"Creating a tibble to test different degrees of freedom (1:10) for natural splines\",\"Using unnest function to get tidy versions of different models\",\"Visualising fitted values of all 6 different models at the same time\",\"Investigating whether the model got \\\"better\\\" as we added degrees of freedom to the natural splines, using the glance function\",\"Using ANOVA to perform a statistical test on whether natural splines as a group explain variation in MPG\",\"Exploring colinearity of dependant variables (displacement and cylinders)\",\"Binning years into every two years using floor function\",\"Using summarise_at function to do quick averaging of multiple variables\",\"Extracting digits (release year) from character string using regex, along with good explanation of extract function\",\"Quick check on why parse_number is unable to parse some values -- is it because they are NA or some other reason?\",\"Visually investigating correlation between budget and rating\",\"Investigating correlation between MPAA rating (PG-13, R, etc.) and rating using boxplots\",\"Using pull function to quickly check levels of a factor\",\"Using ANOVA to check difference of variation within groups (MPAA rating) than between groups\",\"Separating genre using separate_rows function (instead of str_split and unnest)\",\"Removing boilerplate \\\"Directed by...\\\" and \\\"With...\\\" part of plot variable and isolating plot, first using regex, then by using separate function with periods as separator\",\"Unnesting word tokens, removing stop words, and counting appearances\",\"Aggregating by word to find words that appear in high- or low-rated movies\",\"Discussing potential confounding factors for ratings associated with specific words\",\"Searching for duplicated movie titles\",\"De-duping using distinct function\",\"Loading in and explaining glmnet package\",\"Using movie titles to pull out ratings using rownmaes and match functions to create an index of which rating to pull out of the original dataset\",\"Actually using glmnet function to create lasso model\",\"Showing built-in plot of lasso lambda against mean-squared error\",\"Explaining when certain terms appeared in the lasso model as the lambda value dropped\",\"Gathering all variables except for title, so that the dataset is very tall\",\"Using unite function to combine two variables (better alternative to paste)\",\"Creating a new lasso with tons of new variables other than plot words\",\"Starter EDA of latitude and longitude using geom_point\",\"Aggregating squirrel counts by hectare to get a \\\"binned\\\" map\",\"Investigating colour notes\",\"Asking question, \\\"Are there areas of the parks where we see certain-coloured squirrels\",\"Plotting latitude and percentage of gray squirrels to answer, \\\"Do we get a lower proportion of gray squirrels as we go farther north?\\\"\",\"Using logistic regression to test gray squirrel (proportion as we go farther north)\",\"Noting that he could have used original data sets as input for logistic regression function\",\"\\\"Does a squirrel run away?\\\" based on location in the park (latitude), using logistic regression\",\"Using summarise_at function to apply same function to multiple variables\",\"Loading ggmap package\",\"Start using ggmap, with the get_map function\",\"Decision to not set up Google API key to use ggmap properly\",\"Using the sf package to read in a shapefile of Central Park\",\"Using read_sf function from sf package to import a shapefile into R\",\"Using geom_sf function from sf package to visualise the imported shapefile\",\"Combining shapefile \\\"background\\\" with relevant squirrel data in one plot\",\"Visualising pathways (footpaths, bicycle paths) in the shapefile\",\"Finishing visualisation and moving on to analysing activity types\",\"Selecting fields based on whether they end with \\\"ing\\\", then gathering those fields into tidy format\",\"Decision to create a Shiny visualisation\",\"Setting Shiny app settings (e.g., slider for minimum number of squirrels)\",\"Setting up Shiny app options / variables\",\"Explanation of why setting up options in Shiny app the way he did\",\"Solving error \\\"Discrete value supplied to continuous scale\\\"\",\"First draft of Shiny app\",\"Creating a dynamic midpoint for the two-gradient scale in the app\",\"Adding additional variables of more behaviours to Shiny app (kuks, moans, runs from, etc.)\",\"\\\"What are the distributions of some of these [behaviours]?\\\"\",\"Adding ground location (above ground, ground plane) to Shiny app\",\"Summary of screencast\",\"Summarizing many things by language (e.g., lines of code, comment/code ratio)\",\"Using gather function to consolidate multiple metrics into one dimension, then visualizing by facetting by metric\",\"Setting ncol = 1 within facet_wrap function to get facetted graphs to stack vertically\",\"Using reorder_within function (tidytext package) to properly reorder factors within each facet\",\"Using geom_text label to add language name as label to scatter points\",\"Completing preliminary overview and looking at distribution of R code in packages\",\"Using str_extract to extract only letters and names from character vector (using regex)\",\"Re-ordering the order of categorical variables in the legend using guides function\",\"Investigating comment/code ratio\",\"Importing additional package data (looking around for a bit, then starting to actually import ~46:00)\",\"Importing even more additional data (available packages)\",\"Using separate_rows function to separate delimited values\",\"Using extract function and regex to pull out specific types of characters from a string\",\"Summary of screencast\",\"Using read_lines function to import a plain text file (.txt)\",\"Using str_detect function to filter out words that do not contain the letter \\\"g\\\"\",\"Using str_split function to get a list of a word's individual letters\",\"Using setdiff function to find words with invalid letters (letters that are not in the puzzle honeycomb) -- also needs map function (at 4:35)\",\"Changing existing code to make a function that will calculate scores for letter combinations\",\"Noticing the rule about bonus points for pangrams and using n_distinct function to determine if a word gets those points\",\"Using map function to eliminate duplicate letters from each word's list of component letters\",\"Using acast function from reshape2 package to create a matrix of words by letters\",\"Using a the words/letters matrix to find valid words for a given letter combination\",\"Using the matrix multiplication operator %*% to find the number of \\\"forbidden\\\" letters for each word\",\"Using microbenchmark function from microbenchmark package to test how long it takes to run a function\",\"Using combn function to get the actual combinations of 6 letters (not just the count)\",\"Using map function to get scores for different combinations of letters created above\",\"Using which.max function to find the position of the max value in a vector\",\"Using t function to transpose a matrix\",\"Summary of screencast\",\"Overview of transcripts data\",\"Overview of ratintgs data\",\"Using fct_inorder function to create a factor with levels based on when they appear in the dataframe\",\"Using theme and element_text to turn axis labels 90 degrees\",\"Creating a line graph with points at each observation (using geom_line and geom_point)\",\"Adding text labels to very high and very low-rated episodes\",\"Using theme function's panel.grid.major argument to get rid of some extraneous gridlines, using element_blank function\",\"Using geom_text_repel from ggrepel package to experiment with different labelling (before abandoning this approach)\",\"Using row_number function to add episode_number field to make graphing easier\",\"Explanation of why number of ratings (votes) is relevant to interpreting the graph\",\"Using unnest_tokens function from tidytext package to split full-sentence text field to individual words\",\"Using anti_join function to filter out stop words (e.g., and, or, the)\",\"Using str_remove_all function to get rid of quotation marks from character names (quirks that might pop up when parsing)\",\"Asking, \\\"Are there words that are specific to certain characters?\\\" (using bind_tf_idf function)\",\"Using reorder_within function to re-order factors within a grouping (when a term appears in multiple groups) and scale_x_reordered function to graph\",\"Asking, \\\"What effects the popularity of an episode?\\\"\",\"Dealing with inconsistent episode names between datasets\",\"Using str_remove function and some regex to remove \\\"(Parts 1&2)\\\" from some episode names\",\"Using str_to_lower function to further align episode names (addresses inconsistent capitalization)\",\"Setting up dataframe of features for a LASSO regression, with director and writer each being a feature with its own line\",\"Using separate_rows function to separate episodes with multiple writers so that each has their own row\",\"Using log2 function to transform number of lines fields to something more useable (since it is log-normally distributed)\",\"Using cast_sparse function from tidytext package to create a sparse matrix of features by episode\",\"Using semi_join function as a \\\"filtering join\\\"\",\"Setting up dataframes (after we have our features) to run LASSO regression\",\"Using cv.glmnet function from glmnet package to run a cross-validated LASSO regression\",\"Explanation of how to pick a lambda penalty parameter\",\"Explanation of output of LASSO model\",\"Outline of why David likes regularized linear models (which is what LASSO is)\",\"Summary of screencast\",\"Disclaimer that David's not an epidemiologist\",\"Overview of dataset\",\"Using dir function with its full.names argument to get file paths for all files in a folder\",\"Inspecting JSON-formatted data\",\"Introducing hoist function as a way to deal with nested lists (typical for JSON data)\",\"Continuing to use the hoist function\",\"Brief explanation of pluck specification\",\"Using object.size function to check size of json data\",\"Using map_chr and str_c functions together to combine paragraphs of text in a list into a single character string\",\"Using unnest_tokens function from tidytext package to split full paragraphs into individual words\",\"Overview of scispaCy package for Python, which has named entity recognition features\",\"Introducting spacyr package, which is a R wrapper around the Python scispaCy package\",\"Showing how tidytext can use a custom tokenization function (David uses spacyr package's named entity recognition)\",\"Demonstrating the tokenize_words function from the tokenizers package\",\"Actually using a custom tokenizer in unnest_tokens function\",\"Using sample_n function to get a random sample of n rows\",\"Asking, \\\"What are groups of words that tend to occur together?\\\"\",\"Using pairwise_cor from widyr package to find correlation between named entities\",\"Using ggraph and igraph packages to create a network plot\",\"Starting to look at papers' references\",\"Using unnest_longer then unnest_wider function to convert lists into a tibble\",\"Using str_trunc function to truncate long character strings to a certain number of characters\",\"Using glue function for easy combination of strings and R code\",\"Summary of screencast\",\"Overview of JSON files with the data David will make a package of\",\"Starting to create a new package with \\\"New Project\\\" in RStudio\",\"Creating a file to reference the license for the dataset\",\"Using use_data_raw function from usethis package to set up a folder structure and preliminary function for raw data\",\"Explanation that we want to limit the number of packages we load when building a package (e.g., no library(tidyverse) )\",\"Using use_package function from usethis package to add \\\"Suggested packages\\\"\",\"Reviewing import and cleaning code already completed\",\"Using roxygen2 package to write documentation\",\"More documentation writing\",\"Using use_data function from usethis package to create a folder structure and datafile for (finished/cleaned) data\",\"Making a mistake clicking \\\"Install and Restart\\\" button on the \\\"Build\\\" tab (because of huge objects in the environment) (see 26:50 for alternative)\",\"Using load_all function from devtrools package as an alternative to \\\"Install and Restart\\\" from above step\",\"Using document function from devtools package to process written documentation\",\"De-duplicating paper data in a way the keeps records that have fewer missing values than other records for the same paper\",\"Using use_data function with its overwrite argument to overwrite existing data\",\"Writing documentation for paragraphs data\",\"Testing an install of the package\",\"Adding link to code in documentation\",\"Writing examples of how to use the package (in documentation)\",\"Discussion of outstanding items that David hasn't done yet (e.g., readme, vignettes, tests)\",\"Creating a simple readme, including examples, with use_readme_rmd function from usethis package\",\"Using knit function from the knitr package to knit the readme into a markdown file\",\"Creating a GitHub repository to host the package (includes how to commit to a GitHub repo using RStudio's GUI)\",\"Explanation that version 0.0.0.9000 means that the package is in early development\",\"Actually creating the GitHub repository\",\"Overview of remaining tasks\",\"Simple explanation of accumulate function\",\"Example using letters\",\"Using tilde ~ to create an anonymous function\",\"Introducing Pascal's Triangle\",\"Starting to create Pascal's triangle in R\",\"Concerting the conceptual solution into an accumulate function\",\"Explaining why the recursive nature of this problem is well-suited to simulation\",\"Introducing the accumulate function as a tool for simulation\",\"Creating a condition to call the done function\",\"After creating a function to simulate one round of the problem, using replicate function to run simulation many times\",\"Using qplot function to quickly create a histogram of simulations\",\"Making observations on the distribution of simulations (looks kind of like a gamma distribution)\",\"Observing that the distribution is kind of log-normal (but that doesn't really apply because we're using integers)\",\"Using table and sort functions to find the most common number of rolls\",\"Starting the Extra Credit portion of the problem (N-sided die)\",\"Using the crossing function to set up a tibble to run simulations\",\"Using map_dbl function to apply a set of simulations to each possibility of N sides\",\"Spotting an error in the formula for simulating one round (6-sided die was hard-coded)\",\"Using simple linear regression with the lm function to find the relationship between number of sides and average number of rolls\",\"Reviewing distributions for different N-sided dice\",\"Calculating variance, standard deviation, and coefficient of variation to get hints on the distribution (and ruling out Poisson)\",\"Asking, \\\"What ingredients are used in beer?\\\"\",\"Using filter and max functions to look at the most recent period of time\",\"Using paste and ymd functions (ymd is from lubridate package) to convert year-month field into an date-formatted field\",\"Spotting potential missing or mis-parsed data\",\"Introducing the tidymetrics framework\",\"Using install_github function to install tidymetrics from GitHub\",\"Using cross_by_dimensions function from tidymetrics package to get aggregations at different levels of multiple dimensions\",\"Using cross_by_periods function from tidymetrics package to also get aggregations for different intervals (e.g, month, quarter, year)\",\"Using use_metrics_scaffold function from tidymetrics package to create framework for documenting dimensions in RMarkdown YAML header\",\"Using create_metrics function from tidymetrics package to save data as a tibble with useful metadata (good for visualizing interactively)\",\"Using preview_metric function from shinymetrics package (still under development as of 2020-04-24) to demonstrate shinymetrics\",\"Succesfuly getting shinymetrics to work\",\"Explanation of the shinymetrics bug David ran into\",\"Changing order of ordinal variable (e.g., \\\"1,000 to 10,000\\\" and \\\"10,000 to 20,000\\\") using the parse_number, fct_lump, and coalesce functions\",\"Asking, \\\"Where is beer produced?\\\"\",\"Looking up sf package documentation to refresh memory on how to draw state borders for a map\",\"Using match function and state.abb vector (state abbreviations) from sf package to perform a lookup of state names\",\"Using geom_sf function (and working through some hiccoughs) to create a choropleth map\",\"Using theme_map function from ggthemes package to get more appropriate styling for maps\",\"Experimenting with how to get the legend to display in the bottom right corner\",\"Starting to build an animation of consumption patterns over time using gganimate package\",\"Getting the year being animated to show up in the title of a gganimate map\",\"Summary of screencast\",\"Spotting a mistake in a group_by call causing the percentages not to add up properly\",\"Brief extra overview of tidymetrics code\",\"Introducing accumulate functon as a possible solution (but not used here)\",\"Using sample function to simulate 1000 rolls of a 10-sided die\",\"Explanation of dividing sample rolls into streaks (instead of using logic similar to a while loop)\",\"Using cumsum function to separate 1000 rolls into individual sequences (which end when a 0 is rolled)\",\"Using lag function to \\\"shift\\\" sequence numbering down by one row\",\"Using cummax and lag functions to check whether a roll is less than the highest value rolled previously in the sequence\",\"Fixing previous step with cummin function (instead of cummax) and dropping the lag function\",\"Finished simulation code and starting to calculate scores\",\"Using -row_number function (note the minus sign!) to calculate decimal position of number in the score\",\"Investigating the distribution of scores\",\"Using seq function in the breaks argument of scale_x_continuous to set custom, evenly-spaced axis ticks and labels\",\"Getting an overview of the data\",\"Aggregating data into decades using the truncated division operator %/%\",\"Noting that death data is right-censored (i.e., some winners are still alive)\",\"Using transmute function, which combines functionality of mutate (to create new variables) and select (to choose variables to keep)\",\"Using survfit function from survival package to conduct survival analysis\",\"Using glance function from broom package to get a one-row model summary of the survival model\",\"Using extract function to pull out a string matching a regular expression from a variable (stage number in this case)\",\"Theorizing that there is a parsing issue with the original data's time field\",\"Using group_by function's built-in \\\"peeling\\\" feature, where a summarise call will \\\"peel away\\\" one group but left other groupings intact\",\"Using rank function, then upgrading to percent_rank function to give percentile rankings (between 0 and 1)\",\"Using geom_smooth function with method argument as \\\"lm\\\" to plot a linear regression\",\"Using cut function to bin numbers (percentiles in this case) into categories\",\"Reviewing boxplots exploring relationship between first-stage performance and overall Tour performance\",\"Starting to create an animation using gganimate package\",\"Actually writing the code to create the animation\",\"Using reorder_within function from tidytext package to re-order factors that have the same name across multiple groups\",\"Summary of screencast\",\"Explanation of a Poisson process\",\"Asking \\\"How long do you have to wait for X to happen?\\\", which the Exponential distribution can answer\",\"Using `rexp` function to generate numbers from the Exponential distribution\",\"Using a vector of rates inside the `rexp` function (to explore consecutive waiting times)\",\"Using `cumsum` function to calculate total waiting time until hitting a specific number in the Poisson process\",\"Using `which` function to determine the first instance > 3 in a vector\",\"Using `replicate` function to do a quick simulation of the function just written\",\"Discussing methods of making the simulation function faster\",\"Using `crossing` function to set up \\\"tidy\\\" simulation (gives you all possible combinations of values you provide it)\",\"Noting how the consecutive waiting times seems to follow the Harmonic series\",\"Noticing that we are missing trials with 0 comments and fixing\",\"Using `nls` function (non-linear least squares) to test how well the data fits with an exponential curve\",\"Visualizing fit between data and the exponential curve calculated with `nls` in previous step\",\"Using `augment` function to added fitted values of the `nls` function\",\"Exploring whether the data actually follows a Geometric distribution\",\"Explanation of the Geometric distribution as it applies to this question\",\"Generalizing the question to ask how long it takes to get to multiple comments (not just 3)\",\"Explanation of why we subtract 1 when fitting an exponential curve\",\"Summary of screencast\",\"Use the `mdy` function from the `lubridate` package to change the date variable from `character` class to `date` class.\",\"Use the `rename` function from the `dplyr` package to rename variable in the dataset.\",\"Use the `fct_reorder` function from the `forcats` package to sort the `geom_col` in descending order.\",\"Use the `fct_lump` function from the `forcats` package within `count` to lump together country names except for the 6 most frequent.\",\"Use the `scale_x_continuous` function from `ggplot2` with the `scales` package to change the x-axis values to dollar format.\",\"Use the `month` and `floor_date` function from the `lubridate` package to get the month component from the `date` variable to count the total fines per month.\",\"Use the `na_if` function from the `dplyr` package to convert specific date value to `NA`.\",\"Use the `fct_reorder` function from the `forcats` package to sort the stacked `geom_col` and legend labels in descending order.\",\"Use the `dollar` function from the `scales` package to convert the `price` variable into dollar format.\",\"Use the `str_trunc` to shorten the `summary` string values to 140 characters.\",\"Use the `separate_rows` function from the `tidyr` package with a `regular expression` to separate the values in the `article_violated` variable with each matching group placed in its own row.\",\"Use the `extract` function from the `tidyr` package with a `regular expression` to turn each matching group into a new column.\",\"Use the `geom_jitter` function from the `ggplot2` package to add points to the horizontal box plot.\",\"Use the `inner_join` function from the `dplyr` package to join together `article_titles` and `separated_articles` tables.\",\"Use the `paste0` function from `base R` to concatenate `article` and `article_title`.\",\"Use the `str_detect` function from the `stringr` package to detect the presence of a pattern in a string.\\n\\n\",\"Use the `group_by` and `summarize` functions from the `dplyr` package to aggregate fines that were issued to the same country on the same day allowing for size to be used in `geom_point` plot.\",\"Use the `scale_size_continuous` function from the `ggplot2` package to remove the size legend.\",\"Create an interactive dashboard using the `shinymetrics` and `tidymetrics` which is [a tidy approach to business intelligence](https://github.com/datacamp/tidymetrics).\",\"Use the `cross_by_dimensions` and `cross_by_periods` functions from the `tidyr` package which stacks an extra copy of the table for each dimension specified as an argument (`country`, `article_title`, `type`), replaces the value of the column with the word `All` and `periods`, and groups by all the columns. It acts as an extended group_by that allows complete summaries across each individual dimension and possible combinations.\",\"Use the `cross_by_periods ` function from the `tidymetrics` package to aggregate data over time (`month`, `quarter`, and `year`) then visualize with `geom_line`.\",\"Use the `cross_by_periods ` function from the `tidymetrics` package with `windows = c(28))` to create a 4-week rolling average across `month`, `quarter`, and `year`.\",\"Create and `interactive dashboard` using the `shinymetrics` and `tidymetrics` packages.\",\"Use the `str_remove` function from the `stringr` package to remove matched pattern in a string.\",\"Use the `cross_by_dimensions` function from the `tidymetrics` package which acts as an extended `group_by` that allows complete summaries across each individual dimension and possible combinations.\",\"Use the `shinybones` package to create an interactive dashboard to visualize all 3 metrics at the same time.\",\"Using `crossing` function to set up \\\"tidy\\\" simulation (gives you all possible combinations of values you provide it)\",\"Using `rbinom` function to simulate the number of prisoners who choose to flip, then using `rbinom` again to simulate number of tails\",\"Using `dbinom` function (probability mass function) to see probabilities of any given number of prisoners choosing to flip\",\"Using `map_dbl` function to iterate a function, making sure to return a `dbl`-class object\",\"Using `seq_len(n)` instead of `1:n` to be slightly more efficient\",\"Using `optimise` function to conduct single-dimension optimisation (for analytical solution to this question)\",\"Using backticks (`like this`) for inline R functions in RMarkdown\",\"Starting the Extra Credit portion of the problem (N prisoners instead of 4)\",\"Using `map2_dbl` function to iterate a function that requires two inputs (and make sure it returns a `dbl`-class object)\",\"Reviewing visualisation of probabilties with a varying numbers of prisoners\",\"Tweaking graph to look nicer\",\"Get the exact optimal probability value for each number of prisoners\",\"Troubleshooting `optimise` function to work when iterated over different numbers of prisoners\",\"Using `unnest_wider` function to disaggregate a list, but put different elements on separate columns (not separate rows, which `unnest` does\",\"Explanation of what happens to probabilities as number of prisoners increases\",\"Summary of screencast\",\"Starting text analysis of critic reviews of Animal Crossing\",\"Using floor_date function from lubridate package to round dates down to nearest month (then week)\",\"Using unnest_tokens function and anti_join functions from tidytext package to break reviews into individual words and remove stop words\",\"Taking the average rating associated with individual words (simple approach to gauge sentiment)\",\"Using geom_line and geom_point to graph ratings over time\",\"Using mean function and logical statement to calculate percentages that meet a certain condition\",\"Using geom_text to visualize what words are associated with positive/negative reviews\",\"Disclaimer that this exploration is not text regression -- wine ratings screencast is a good resource for that\",\"Starting to do topic modelling\",\"Explanation of stm function from stm package\",\"Explanation of stm function's output (topic modelling output)\",\"Changing the number of topics from 4 to 6\",\"Explanation of how topic modelling works conceptually\",\"Using tidy function from broom package to find which \\\"documents\\\" (reviews) were the \\\"strongest\\\" representation of each topic\",\"Noting that there might be a scraping issue resulting in review text being repeated\",\"(Unsuccessfully) Using str_sub function to help fix repeated review text by locating where in the review text starts being repeated\",\"(Unsuccessfully) Using str_replace and map2_chr functions, as well as regex cpaturing groups to fix repeated text\",\"Looking at the association between review grade and gamma of the topic model (how \\\"strong\\\" a review represents a topic)\",\"Using cor function with method = \\\"spearman\\\" to calculate correlation based on rank instead of actual values\",\"Summary of screencast\",\"Change the `last_eruption_year` into `years_ago` by using `mutate` from the `dplyr` package with `years_ago = 2020 - as.numeric(last_eruption_year))`. In the plot David includes `+1` to account for 0 values in the `years_ago` variable.\",\"Use `str_detect` from the `stringr` package to search the `volcano_name` variable for `Vesuvius` when not sure if spelling is correct.\",\"Use the `longitude` and `latitude` to create a world map showing where the volcanoes are located.\",\"Use `fct_lump` from the`forcats` package to lump together all `primary_volcano_type` factor levels except for the `n` most frequent.\",\"Use `str_remove` from the `stringr` package with the regular expression `\\\"\\\\\\\\(.\\\\\\\\)\\\"` to remove the parentheses.\",\"Use the `leaflet` package to create an interactive map with popup information about each volcano.\",\"Use `glue` from the `glue` package to create an `HTML` string by concatenating `volcano_name` and `primary_volcano_type` between `HTML

    <\\/p> tags`.\",\"Use the `DT` package to turn the `leaflet` popup information into a `datatable`.\",\"Use `str_replace_all` fromt he `stringr` package to replace all the underscores `_` in `volcano_name` with space. Then use `str_to_title` from the `stringr` package to convert the `volcano_name` variable to title case.\",\"Use `kable` with `format = HTML` from the `knitr` package instead of `DT` to make turning the data into `HTML` much easier.\",\"Use `paste0` from `base` R to bold the `Volcano Name`, `Primary Volcano Type`, and `Last Eruption Year` in the `leaflet` popup.\",\"Use `replace_na` from the `tidyr` package to replace `unknown` with `NA`.\",\"Use `addMeasure` from the `leaflet` package to add a tool to the map that allows for the measuring of distance between points.\",\"Use `colorNumeric` from the `leaflet` package to color the points based on their `population within 5km`. To accomplish this, David creates 2 new variables: 1) `transformed_pop` to get the population on a `log2` scale & 2) `pop_color` which uses the `colorNumeric` function to generate the color hex values based on `transformed_pop`.\",\"Use the `gganimate` package to create an animated map.\",\"Use `geom_point` from the `ggplot2` package with `size = .00001 * 10 ^ vei` so the size of the points are then proportional to the `volume` metrics provided in the `Volcano Eruption Index`. The metrics are in `Km^3`.\",\"Use `scale_size_continuous` from the `ggplot2` package with `range = c(.1, 6)` to make the smaller points smaller and larger points larger.\",\"Use `scale_color_gradient2` from the `ggplot2` package to apply color gradient to each point based on the volcano size and whether its low or high.\",\"Summary of screencast while waiting for `gganimate` map to render. \\n\\nAlso, brief discussion on using `transition_reveal` instead of `transition_time` to keep the point on the map instead of replacing them in each frame.\",\"Use `pivot_longer` from the `dplyr` package to pivot the data set from `wide` to `long`.\",\"Use `mutate_at` from the `dplyr` package with `starts_with` to change the class to `character` for all columns that start with `w_` and `l_`.\",\"Use `separate` from the `tidyr` package to separate the `name` variable into three columns with `extra = merge` and `fill = right`.\",\"Use `rename` from the `dplyr` package to rename `w_player1`, `w_player2`, `l_player1`, and `l_player2`.\",\"Use `pivot_wider` from the `dplyr` package to pivot the `name` variable from `long` to `wide`.\",\"Use `str_to_upper` to convert the `winner_loser` `w` and `l` values to uppercase.\",\"Add unique row numbers for each match using `mutate` with `row_number` from the `dplyr` package.\",\"Separate the `score` values into multiple rows using `separate_rows` from the `tidyr` package.\",\"Use `separate` from the `tidyr` package to actual scores into two columns, one for the winners score `w_score` and another for the losers score `l_score`.\",\"Use `na_if` from the `dplyr` package to change the `Forfeit or other` value from the `score` variable to `NA`.\",\"Use `str_remove` from the `stringr` package to remove scores that include `retired`.\",\"Determine how many times the winners score `w_score` is greter than the losers score `l_score` at least 1/3 of the time.\",\"Use `summarize` from the `dplyr` package to create the summary statistics including the `number of matches`, `winning percentage`, `date of first match`, `date of most recent match`.\",\"Use `type_convert` from the `readr` package to convert `character` class variables to `numeric`.\",\"Use `summarize_all` from the `dplyr` package to calculate the calculate which fraction of the data is not `NA`.\",\"Use `summarize` from the `dplyr` package to determine players `number of matches`, `winning percentage`, `average attacks`, `average errors`, `average kills`, `average aces`, `average serve errors`, and `total rows with data` for years prior to 2019. \\n\\nThe summary statistics are then used to answer how would we could predict if a player will win in 2019 using `geom_point` and `logistic regression`. Initially, David wanted to predict performance based on players first year performance. (NOTE - David mistakingly grouped by `year` and `age`. He cathces this around 1:02:00.)\",\"Use `year` from the `lubridate` package within a `group_by` to determine the `age` for each play given their `birthdate`.\",\"Turn the summary statistics at timestamp `42:00` into a `.` DOT `%>%` PIPE function.\",\"Summary of screencast.\",\"Use `fct_reorder` from the `forcats` package to reorder the `ingredient` factor levels along `n`.\",\"Use `fct_lump` from the `forcats` package to lump together all the levels except the `n` most frequent in the `category` and `ingredient` variables.\",\"Use `pairwise_cor` from the `widyr` package to find the correlation between the `ingredients`.\",\"Use `reorder_within` from the `tidytext` package with `scale_x_reordered` to reorder the the columns in each `facet`.\",\"Use the `ggraph` and `igraph` packages to create a `network diagram`\",\"Use `extract` from the `tidyr` package with `regex = (.*) oz` to create a new variable `amount` which doesn't include the `oz`.\",\"Use `extract` with `regex` to turn the strings in the new `amount` variable into separate columns for the `ones`, `numerator`, and `denominator`.\",\"Use `replace_na` from the `tidyr` package to replace `NA` with zeros in the `ones`, `numberator`, and `denominator` columns. David ends up reaplcing the `zero` in the `denominator` column with ones in order for the calculation to work.\",\"Use `geom_text_repel` from the `ggrepel` package to add `ingredient` labels to the `geom_point` plot.\",\"Use `na_if` from the `dplyr` package to replace `zeros` with `NA`\",\"Use `scale_size_continuous` with `labels = percent_format()` to convert size legend values to percent.\",\"Change the size of the points in the `network diagram` proportional to `n` using `vertices = ingredient_info` within `graph_from_data_frame` and `aes(size = n)` within `geom_node_point`.\",\"Use `widely_svd` from the `widyr` package to perform principle component analysis on the `ingredients`.\",\"Use `paste0` to concatenate `PC` and `dimension` in the facet panel titles.\",\"Summary of screencast.\",\"Use ` fct_reorder` from the `forcats` package to reorder the `category` factor levels by sorting along `n`.\",\"Use `str_remove` from the `stringr` package to remove anything after a bracket or parenthesis from the `person` variable with the `regular expression` `\\\"[\\\\\\\\[\\\\\\\\(].*\\\"` David then discusses how web scraping may be a better option than parsing the strings.\",\"Use `str_trim` from the `stringr` package to remove the `whitespace` from the `person` variable. David then discusses how web scraping may be a better option than parsing the strings.\",\"Create an interactive `plotly` timeline.\",\"Use `ylim(c(-.1, 1))` to set scale limits moving the `geom_point` to the bottom of the graph.\",\"Use `paste0` from `base R` to concatenate the `accomplishment` and `person` with `\\\": \\\"` in between the two displayed in the timeline hover label.\",\"Set `y` to `category` in `ggplot` `aesthetics` to get 8 separate timelines on one plot, one for each category. Doing this allows David to remove the `ylim` mentioned above.\",\"Use the `plotly` `tooltip = text` parameter to get just a single line of text in the `plotly` hover labels.\",\"Use `glue` from the `glue` package to reformat `text` with `\\\\n` included so that the single line of text can now be broken up into 2 separate lines in the hover labels.\",\"Use `separate_rows` from the `tidyr` package to separate the `occupation_s` variable from the `science` dataset into multiple columns delimited by a semicolon with `sep = \\\"; \\\"`\",\"Use `str_to_title` from the `stringr` package to conver the case to title case in the `occupation_s` variable.\",\"Use `str_detect` from the `stringr` package to detect the presence of `statistician` from within the `occupation_s` variable with `regex(\\\"statistician\\\", ignore_case = TRUE)` to perform a case-insensitive search.\",\"Use the `rvest` package with `Selector Gadget` to scrape additional information about the individual from their `Wikipedia` infobox.\",\"Use `map` and `possibly` from the `purrr` package to separate out the downloading of data from parsing the useful information. David then turns the infobox extraction step into an `anonymous function` using `.%>%` dot-pipe.\",\"Summary of screencast.\",\"Use `fct_lump` from the `forcats` package to lump together all the factor levels in `ship_name` except the `n` most frequent. Used within `filter` with `! = \\\"Other\\\"` to remove `other`.\",\"use `fct_reorder` from the `forcats` package to reorder the `ship_name` factor levels y sorting along the `n_slaves_arrived` variable.\",\"Add `geom_vline` to `geom_histogram` to annotate the plot with a vertical line indicating the Revolutionary War and the Civil War.\",\"Use `truncated division` within `count` to create a new `decade` variable equal to `10 * (year_arrival %/% 10))`\",\"Use `str_trunc` from the `stringr` package to truncate the titles in each facet panel accounting for the slave ports with really long names.\",\"Another option for accounting for long titles in the facet panels is to use `strip.text` within `theme` with `element_text(size = 6)`\",\"Use the `ggraph` package to create a `network diagram` using `port_origin` and `port_arrival`.\",\"Use `arrow` from the `grid` package to add directional arrows to the points in the `network diagram`.\",\"Use `scale_width_size_continuous` from the `ggraph` packge to adjust the size of the points in the `network diagram`.\",\"Within `summarize` use `mean(n_slaves_arrived, na.rm = TRUE) * n())` to come up with an estimated total numer of slaves since 49% of the data is missing.\",\"Create a faceted stacked percent barplot (spinogram) showing the percentage of `black_free`, `black_slaves`, `white`, and `other` for each region.\",\"Use the `wordcloud` package to create a `wordcloud` with the `african_names` dataset. David hsa issues with the `wordcloud` package and opts to use `ggwordcloud` instead. Also, mentions the `worldcloud2` package.\",\"Use `fct_recode` from the `forcats` package to change the factor levels for the `gender` variable while renaming `Man = \\\"Boy\\\"` and `Woman = \\\"Girl\\\"`\",\"Use `reorder_within` from the `tidytext` package to reorder the `geom_col` by `n` within `gender` variable for each facet panel.\",\"Summary of screencast.\",\"Use `summarize` and `across` to calculate the proportion of `NA` values in the `individuals` dataset. Note, you do not need to use `list()`.\",\"Use `ggplot` and `borders` from the `ggplot2` package to create a map of `Canada` with `deploy_on_longitude` and `deploy_on_latitude` from the `individuals` dataset.\",\"Import Canada province `shapefile` using the `sf` package. [Unsuccessful]\",\"Use `min` and `max` from `base r ` within `summarize` to find out the `start` and `end` dates for each caribou in the `locations` dataset.\",\"Use `sample` from `base r` to pick one single caribou at a time then use the subset with `geom_path` from `ggplot2` to track the path a that caribou takes over time. `color = factor(floor_date(timestamp, \\\"quarter\\\")` is used to color the path according to what quarter the observation occured in.\",\"Use `as.Date` from `base r` and `floor_date` from the `lubridate` package to convert `timestamp` variable into quarters then `facet_wrap` the previous plot by `quarter`.\",\"Within `mutate`, use `as.numeric(difftime(timestamp, lag(timestamp), unit = \\\"hours\\\"))` from `base r` to figure out the gap in time between observations.\",\"Use `distHaversine` from the `geosphere` package to calculate distance in `km` then convert it to speed in `kph`.\",\"Summary of dataset.\",\"Using `separate` to separate the name from secrete identity in the `character` column\",\"Using `summarize` and `across` to find the frequency of the action variables and find out how many issues each action was used for each character\",\"Create a `geom_col` chart to visualize which character speaks in the most issues\",\"Create a `geom_point` chart to visualize each character’s average lines per issue in which the character is depicted\",\"Create a `geom_point` chart to visualize each character’s average thoughts per issue in which the character is depicted\",\"Create a `geom_point` chart to visualize character’s speech versus thought ratio per issue in which the character is depicted\",\"Create a `geom_point` to visualize character’s number of lines while in costume versus not in costume\",\"Create a `geom_point` chart to visualize the lines in costume versus lines out of costume ratio\",\"Create a `lollipop graph` using `geom_point` and `geom_errorbarh` to visualize the lines in costume versus lines out of costume ratio and their distance from 1.0 (1 to 1)\",\"Use `summarize` to find the frequency of each location and the total number of unique issues where the location is used\",\"Use `summarize` and `fct_lump` to count how many issues each author has written while lumping together all authors except the most frequent\",\"Use `summarize` and `fct_lump` to see if the authors rates of passing the Bechdel test differ from one another\",\"Create a `geom_line` chart to visualize if the rates of passing the Bechdel test changed over time and `floor division` `%/%` to generate 20 observations per group\",\"Create a `geom_col` to visualize the amount of lines each character has per issue over time giving context to Bechdel test passing rates\",\"Summary of screencast\",\"Using `fct_lump` within `count` and then `mutate` to lump the variety of coffee together except for the most frequent\",\"Create a `geom_boxplot` to visualize the variety and the distribution of `total_cup_points`\",\"Create a `geom_histogram` to visualize the variety and the distribution of `total_cup_points`\",\"Using `fct_reorder` to reorder `variety` by sorting it along `total_cup_points` in ascending order\",\"Using `summarize` with `across` to calculate the percent of missing data (NA) for each rating variable\",\"Create a bar chart using `geom_col` with `fct_lump` to visualize the frequency of top countries\",\"Using `pivot_longer` to pivot the rating metrics for wide format to long format\",\"Create a `geom_line` chart to see if the `sum` of the rating categories equal to the `total_cup_points` column\",\"Create a `geom_density_ridges` chart to show the distribution of ratings across each rating metric\",\"Using `summarize` with `mean` and `sd` to show the average rating per metric with its standard deviation\",\"Using `pairwise_cor` to find correlations amongst the rating metrics\",\"Create a `network plot` to show the clustering of the rating metrics\",\"Using `widely_svd` to visualize the biggest source of variation with the rating metrics (Singular value decomposition)\",\"Create a `geom_histogram` to visualize the distribution of altitude\",\"Using `pmin` to set a maximum numeric altitude value of 3000\",\"Create a `geom-point` chart to visualize the correlation between altitude and quality (`total_cup_points`)\",\"Using `summarize` with `cor` to show the correlation between altitude and each rating metric\",\"Create a linear model `lm` for each rating metric then visualize the results using a `geom_line` chart to show how each kilometer of altitude contributes to the score\",\"Summary of screencast\",\"Using `use_tidytemplate` to open the project dataset with the package's tidytemplate Rmd\",\"Using `rename` to rename `Total` column to `total`\",\"Using `fct_reorder` to reorder stacked barplot with `weight = sum`\",\"Using `fct_lump` with `w = n` to lump together `outcome` factor levels displaying the most frequenct with rest lumped into `other`\",\"Using `fct_recode` to combine the factor level `In Stock` with `Currently In Care`\",\"Using `fct_reorder` to reorder `facet_wrap` panels\",\"Using `scale_y_continuous` with `labels = comma` to separate digits with comma\",\"Using `complete` to complete account for missing combinations of data where the value is 0 in the `released` column\",\"Using `max (year)` within `filter` to subset the data displaying only the most recent year\",\"Using `pivot_longer` to pivot location variables from wide to long\",\"Web Scaraping table from Wikipedia with `SelectorGadget` and `Rvest`\",\"Using `str_to_upper` to upper case the values in the `shorthand` column\",\"Using `parse_number` to remove commas from `population` and `area` columns\",\"Using `bind_rows` to bind the two web scraped tables from Wikipedia together by row and column\",\"Using `inner_join` to combine the Wikipedia table with the original data set\",\"Using `mutate` to create new `per_capita_million` column to show `outcome` on a per million people basis\",\"Using `summarize` to create new column `pct_euthanized` showing percent of cats and dogs euthanized over time. Formula accounts for 0 values thus avoiding a resulting empty vector.\",\"Using `scale_y_continuous` with `labels = percent` to add percentage sign to y-axis values\",\"Create a choropleth map of Australia using an Australian States `Shapefile` using the `sf` and `ggplot2` packages | Troubleshooting begins at 44:25 (downsizing / downsampling with `sf_simplify`)\",\"Add animation to the map of Australia showing the percent of cats euthanized by region using `gganimate`\",\"Summary of screencast\",\"Create a pivoted histogram plot to visualize the distribution of penguin metrics using `pivot_longer`, `geom_histogram`, and `facet_wrap`\",\"Create a pivoted density plot to visualize the distribution of penguin metrics using `geom_density` and `facet_wrap`\",\"Create a pivoted boxplot plot to visualize the distribution of penguin metrics using `geom_boxplot` and `facet_wrap`\",\"Create a bar plot to show penguin species changed over time\",\"Create a bar plot to show specie counts per island\",\"Create a logistic regression model to predict if a penguin is Adelie or not using bill length with cross validaiton of metrics\",\"Create second logistic regression model using 4 predictive metrics (bill length, bill depth, flipper length, body mass) and then compare the accuracy of both models\",\"Create a k-nearest neighbor model and then compare accuracy against logistic regression models to see which has the highest cross validated accuracy\",\"What is the accuracy of the testing holdout data on the k-nearest neighbor model?\",\"Create a decision tree and then compare accuracy against the previous models to see which has the highest cross validated accuracy + how to extract a decision tree\",\"Perform multi class regression using `multinom_reg`\",\"Summary of screencast\",\"Using `count` to get an overview of scategorical data\",\"Using `pivot_longer` and `gather` to pivot date variables from wide to long\",\"Using `as.integer` to change `year` variable from `character` to `integer` class\",\"Using `fct_reorder` to reorder stacked barplot\",\"Using `scale_y_continuous` with `labels = comma` from `scales` package to insert a comma every three digits on the y-axis\",\"Using `replace_na` and `list` to replace `NA` values in `country_name` column with United Kingdom\",\"Using `fct_lump` to lump factor levels together except for the 10 most frequent for each facet panel\",\"Using `reorder_within` with `fun = sum` and `scale_y_reordered` to reorder the categories within each facet panel\",\"Using `ggflags` package to add country flags | Debugging strategies include 1) minimal reproducible example and 2) binary search\",\"(Unsuccessfully) Using `fct_recode` to rename the ISO two-digit identifier for the United Kingdom from the UK to GB\",\"Using `ifelse` to replace the ISO two-digit identifier for the United Kingdom from UK to GB & from EL to GR fro Greece | Debugging included\",\"Using `str_to_lower` to convert observations in `country` column to lower case\",\"Creating a `slope graph` to show differences in Nuclear production (2106 versus 2018) | Using `scale_y_log10` to increase distance between points | Using `ggflags` for country flags\",\"Using `scale_x_continuous` with `breaks = c(2016, 2018)` to show only 2016 and 2018 on x-axis\",\"Extend x-axis limits using `scale_x_continuous` with `limits = c(2015, 2019)` and `geom_text` with an `ifelse` within `hjust` to alternate labels for the right and left side of `slope graph`\",\"Creating a slopegraph function\",\"Summary of screencast\",\"Using `count`, `fct_lump`, and `fct_reorder` to get an overview of categorical data\",\"Using `fct_relevel` to reorder the \\\"Before 1900\\\" level to the first location leaving the other levels in their existing order\",\"Using `n` and `sum` in `fct_reorder` to reorder factor levels when there are multiple categories in `count`\",\"Using `reorder_within` and `scale_y_reordered` such that the values are ordered within each facet\",\"Using `axis.text.x\\\" to rotate overlapping labels\",\"Using `filter` and `fct_lump` to lump all levels except for the 8 most frequest facet panels\",\"Using `separate` to separate the character column `binomial_name` into multiple columns (genus and species)\",\"Using `fct_lump` within `count` to lump all levels except for the 8 most frequent genus\",\"Using `rvest` and `SelectorGadget` to web scrape list of species\",\"Using `str_trim` to remove whitespace from character string\",\"Using `separate` to separate character string into genus, species, and rest/citation columns and using `extra = \\\"merge\\\"` to merge extra pieces into the rest/citation column\",\"Using `rvest` and `SelectorGadget` to web scrape image links\",\"Summary of screencast\",\"Use `geom_histogram` to visualize the distribution of episode ratings.\",\"Use `geom_point` and `geom_line` with `color = factor(season)` to visualize the episode rating for every episode.\",\"Use `group_by` and `summarize` to show the average rating for each season and the number of episodes in each season.\",\"Continuing from previous row:\\n\\nUse `geom_line` and `geom_point` with `size = n_episodes` to visualize the average rating for each season with point size indicating the total number of episodes (larger = more episodes, smaller = fewer episodes).\",\"Use `fct_reorder` to reorder the `episode_name` factor levels by sorting along the `episode_rating` variable.\\n\\n\",\"Use `geom_point` to visualize the top episodes by rating. \\n\\nUse the 'glue' package to place `season number` and `episode number` before episode name on the `y axis`.\",\"Use `pivot_longer` to combine ingredients into one single column.\\n\\nUse `separate_rows` with `sep = \\\", \\\"` to separate out the ingredients with each ingredient getting its own row.\",\"Use `fct_lump` to lump ingredients together except for the 10 most frequent.\\n\\nUse `fct_reorder` to reorder `ingredient` factor levels by sorting against `n`.\",\"Use `geom_col` to create a stacked bar plot to visualize the most common ingredients by course.\",\"Use `fct_relevel` to reorder `course` factor levels to appetizer, entree, dessert.\",\"Use `fct_rev` and `scale_fill_discrete` with `guide = guide_legend(reverse = TRUE)` to reorder the segments within the stacked bar plot.\",\"Use the `widyr` package and `pairwise_cor` to find out what ingredients appear together. \\n\\nMentioned: [David Robinson - The {widyr} Package YouTube Talk at 2020 R Conference](https://www.youtube.com/watch?v=mApnx5NJwQA)\",\"Use `ggraph` , `geom_edge_link`, `geom_node_point`, `geom_node_text` to create an ingredient network diagram to show their makeup and how they interact.\",\"Use `pairwise_count` from `widyr` to count the number of times each pair of items appear together within a group defined by feature.\",\"Use `unite` from the `tidyr` package in order to paste together the `episode_course` and `series_episode` columns into one column to figure out if any pairs of ingredients appear together in the same course across episodes.\",\"Use `summarize` with `min`, `mean, `max`, and `n()` to create the `first_season`, `avg_season`, `last_season` and `n_appearances` variables. \\n\\n\",\"Use `slice` with `tail` to get the `n` ingredients that appear in early and late seasons.\",\"Use `geom_boxplot` to visualize the distribution of each ingredient across all seasons.\",\"Fit predictive models (`linear regression` , `random forest`, and `natural spline`) to determine if episode rating is explained by the ingredients or season.\\n\\nUse `pivot_wider` with `values_fill = list(value = 0))` with 1 indicating ingredient was used and 0 indicating it wasn't used.\",\"Summary of screencast.\",\"Using `rename` to shorten column name\",\"Using `rename_all` with `str_remove` and regex to remove characters in column name\",\"Using `pivot_longer` to change data from wide to long\",\"Create a faceted `geom_line` chart\",\"Using `fct_reorder` to reorder facet panels in ascending order\",\"Create an interactive `Shiny` dashboard\",\"Create a faceted `geom_line` chart with `add_count` and `filter(n = max(x))` to subset the data for crops that have observations in every year\",\"Create a faceted `geom_point` chart showing the crop yields at start and end over a 50 year period (1968 start date and 2018 end date)\",\"Create a `geom_boxplot` to visualize the distribution of yield ratios for the different crops to see how efficiency has increased across countries\",\"Create a `geom_col` chart to visualize the median yield ratio for each crop\",\"Create a `geom_point` chart to visualize efficiency imporvement for each country for a specific crop (yield start / yield ratio)\",\"Using the `countrycode` package to color `geom_point` chart by continent names\",\"Summary of screencast\",\"Use `dplyr` package's `count` function to count the unique values of multiple variables.\",\"Use `geom_col` to show how many lines of dialogue there is for each character. Use `fct_reorder` to reorder the `speaker` factor levels by sorting along `n`.\",\"Use `semi_join` to join `friends` dataset with `main_cast` with `by = \\\"speaker` returning all rows from `friends` with a match in `main_cast`.\\n\\n\",\"Use `unite` to create the `episode_number` variable which pastes together `season` and `episode` with `sep = \\\".\\\"`.\\n\\nThen, use `inner_join` to combine above dataset with `friends_info` with `by = c(\\\"season\\\", \\\"episode\\\")`. \\n\\nThen, use `mutate` and the `glue` package instead to combine `{ season }.{ episode } { title }`.\\n\\nThen use `fct_reorder(episode_title, season + .001 * episode)` to order it by `season` first then `episode`.\",\"Use `geom_point` to visualize `episode_title` and `us_views_millions`. \\n\\nUse `as.integer` to change `episode_title` to integer class. \\n\\nAdd labels to `geom_point` using `geom_text` with `check_overlap = TRUE` so text that overlaps previous text in the same layer will not be plotted.\",\"Run the above plot again using `imdb_rating` instead of `us_views_millions`\",\"Ahead of modeling:\\n\\nUse `geom_boxplot` to visualize the distribution of speaking for main characters.\\n\\nUse the `complete` function with `fill = list(n = 0)` to replace existing explicit missing values in the data set.\\n\\nDemonstration of how to account for missing `imdb_rating` values using the `fill` function with `.direction = \\\"downup\\\"` to keep the imdb rating across the same title.\",\"Ahead of modeling:\\n\\nUse `summarize` with `cor(log2(n), imdb_rating)` to find the correlation between speaker and imdb rating -- the fact that the correlation is positive for all speakers gives David a suspicion that some episodes are longer than others because they're in 2 parts with higher ratings due to important moments. David addresses this `confounding factor` by including `percentage of lines` instead of `number of lines`. \\n\\nVisualize results with `geom_boxplot`, `geom_point` with `geom_smooth`.\",\"Use a `linear model` to predict imdb rating based on various variables.\",\"Use the `tidytext` and `tidylo` packages to see what words are most common amongst characters, and whether they are said more times than would be expected by chance. \\n\\nUse `geom_col` to visualize the most overrepresented words per character according to `log_odds_weighted`.\",\"Use the `widyr` package and `pairwise correlation` to determine which characters tend to appear in the same scences together? \\n\\nUse `geom_col` to visualize the correlation between characters.\",\"Summary of screencast.\",\"Using `geom_line` and `summarize` to visualize education spending over time. First for all states. Then individual states. Then small groups of states using `%in%`. Then in random groups of size n using `%in%` and `sample` with `unique`. `fct_reorder` is used to reorder `state` factor levels by sorting along the `inf_adj` variable. \\n\\n`geom_vline` used to add reference to the 2009 financial crisis.\",\"Take the previous chart setting the `inf_adj_perchild` for the first year `1997` to `100%` in order to show a measure of increase from `100%` as opposed to absolute value for change over time for each state relative to `1997`. `geom_hline` used to add reference for the `100%` starting point. David ends up changing the starting point from `100%` to `0%`\\n\\n`fct_reorder` with `max` used to reorder the plots in descending order based on highest peak values.\\n\\nDavid briefly mentions the [small multiples](https://www.sharpsightlabs.com/blog/small-multiples-ggplot/#:~:text=The%20small%20multiples%20technique%20is,groups%20or%20comparing%20over%20time.&text=In%20contrast%2C%20R's%20GGPlot2%20package,multiples%20extraordinarily%20easy%20to%20create.) approach to analyzing data.\",\"Create a `function` named `plot_changed_faceted` to make it easier to visualize the many other variables included in the dataset.\",\"Create a `function` named `plot_faceted` with a `{{ y_axis }}` [embracing](https://dplyr.tidyverse.org/articles/programming.html) argument. Adding this function creates two stages: one for data transformation and another for plotting.\\n\",\"Use the `dir` function with `pattern` and `purrr` package's `map_df` function to read in many different `.csv` files with GDP values for each state. \\n\\nTroubleshooting `Can't combine and columns` error using `function` and `mutate` with `across` and `as.numeric`.\\n\\nExtract state name from filename using `extract` from `tidyr` and `regular expression`. \\n\",\"Unsuccessful attempt at importing state population data via a not user friendly dataset from `census.gov` by skipping the first 3 rows of the Excel file. \\n\\n\",\"Use `geom_col` to see which states spend the most for each child for a single variable and multiple variables using `%in%`.\\n\\nUse `scale_fill_discrete` with `guide_legend(reverse = TRUE)` to change the ordering of the legend.\",\"Use `geom_col` and 'pairwise_corr` to visualize the correlation between variables across states in 2016 using `pairwise correlation`.\",\"Use ` geom_point` to plot `inf_adjust_perchild_PK12ed` versus `inf_adj_perchild_highered`. `geom_text` used to apply state names to each point.\",\"Summary of screencast.\",\"Create a `geom_col` chart to visualize the top 50 tallest mountains.\\r\\n\\r\\nUse `fct_reorder` to reorder the `peak_name` factor levels by sorting along the `height_metres` variable. \\r\",\"Use `summarize` with `across` to get the total number of climbs, climbers, deaths, and first year climbed. \\r\\n\\r\\nUse `mutate` to calculate the percent death rate for members and hired staff.\\r\\n\\r\\nUse `inner_join` and `select` to join with `peaks` dataset by `peak_id`.\\r\\n\",\"Touching on statistical `noise` and how it impacts the death rate for mountains with fewer number of climbs, and how to account for it using various statistical methods including `Beta Binomial Regression` & `Empirical Bayes`.\",\"Further description of `Empirical Bayes` and how to account for not overestimating death rate for mountains with fewer climbers.\\r\\n\\r\\nRecommended reading: [Introduction to Empirical Bayes: Examples from Baseball Statistics](http://varianceexplained.org/r/empirical-bayes-book/) by David Robinson\\r\\n\",\"Use the `ebbr` package (Empirical Bayes for Binomial in R) to create an Empirical Bayes Estimate for each mountain by fitting prior distribution across data and adjusting the death rates down or up based on the prior distributions. \\r\\n\\r\\nUse a `geom_point` chart to visualize the difference between the raw death rate and new `ebbr` fitted death rate.\\r\\n\",\"Use `geom_point` to visualize how deadly each mountain is with `geom_errorbarh` representing the 95% credible interval between minimum and maximum values.\",\"Use `geom_point` to visualize the relationship between `death rate` and `height` of mountain. \\r\\n\\r\\nThere is not a clear relationship, but David does briefly mention how one could use `Beta Binomial Regression` to further inspect for possible relationships / trends. \\r\",\"Use `geom_histogram` and `geom_boxplot` to visualize the distribution of time it took climbers to go from basecamp to the mountain’s high point for successful climbs only.\\r\\n\\r\\nUse `mutate` to calculate the number of days it took climbers to get from basecamp to the highpoint.\\r\\n\\r\\nAdd column to data using `case_when` and `str_detect` to identify strings in `termination_reason` that contain the word `Success` and rename them to `Success` & how to use a `vector` and `%in%` to change multiple values in `termination_reason` to `NA` and rest to `Failed`.\\r\\n\\r\\nUse `fct_lump` to show the top 10 mountains while lumping the other factor levels (mountains) into `other`. \\r\\n\\r\\n\",\"For just Mount Everest, use `geom_histogram` and `geom_density` with `fill = success` to visualize the days from basecamp to highpoint for climbs that ended in `success`, `failure` or `other`.\",\"For just Mount Everest, use `geom_histogram` to see the distribution of climbs per year.\",\"For just Mount Everest, use ‘geom_line` and `geom_point` to visualize `pct_death` over time by decade.\\r\\n\\r\\nUse `mutate` with `pmax` and `integer division` to create a decade variable that lumps together the data for 1970 and before. \\r\\n\",\"Write a function for summary statistics such as `n_climbs`, `pct_success`, `first_climb`, `pct_death`, ‘pct_hired_staff_death`.\",\"For just Mount Everest, use `geom_line` and `geom_point` to visualize `pct_success` over time by decade.\",\"For just Mount Everest, use `geom_line` and `geom_point` to visualize `pct_hired_staff_deaths ` over time by decade.\\r\\n\\r\\nDavid decides to visualize the `pct_hired_staff_deaths` and `pct_death` charts together on the same plot. \\r\\n\",\"For just Mount Everest, fit a logistic regression model to predict the probability of death with `format.pval` to calculate the `p.value`.\\r\\n\\r\\nUse `fct_lump` to lump together all `expedition_role` factors except for the n most frequent. \\r\\n\",\"Use `group_by` with `integer division` and `summarize` to calculate `n_climbers` and `pct_death` for age bucketed into decades.\",\"Use `geom_point` and `geom_errorbarh` to visualize the logistic regression model with confident intervals.\",\"Summary of screencast\",\"Use `fct_reorder` from the `forcats` package to reorder `title` factor levels by sorting along the `sales` variable in `geom_col` plot.\",\"Use `labels = dollar` from the `scales` package to format the `geom_col` x-axis values as currency.\",\"Use `rename_all(str_to_lower)` to convert variable names to lowercase.\",\"Use `unnest_tokens` from the `tidytext` package to split the lyrics into one-lyric-per-row.\",\"Use `anti_join` from the `tidytext` package to find the most common words int he lyrics without `stop_words`.\",\"Use `bind_tf_idf` from the `tidytext` package to determine `tf` - the proportion each word has in each album and `idf` - how specific each word is to each particular album.\",\"Use `reorder_within` with `scale_y_reordered` in order to reorder the bars within each `facet panel`. David replaces `top_n` with `slice_max` from the `dplyr` package in order to show the top 10 words with `ties = FALSE`.\",\"Use `bind_log_odds` from the `tidylo` package to calculate the `log odds ratio` of album and words, that is how much more common is the word in a specific album than across all the other albums.\",\"Use `filter(str_length(word) <= 3)` to come up with a list in order to remove common filler words like `ah`, `uh`, `ha`, `ey`, `eeh`, and `huh`.\",\"Use `mdy` from the `lubridate` package and `str_remove(released, \\\" \\\\\\\\(.*)\\\"))` from the `stringr` package to parse the dates in the `released` variable.\",\"Use `inner_join` from the `dplyr` package to join `taylor_swift_words` with `release_dates`. \\n \\n David ends up having to use `fct_recode` since the albums `reputation` and `folklore` were nor `lowercase` in a previous table thus excluding them from the `inner_join`.\",\"Use `fct_reorder` from the `forcats` package to reorder `album` factor levels by sorting along the `released` variable to be used in the `faceted` `geom_col`.\",\"Use `bind_rows` from hte `dplyr` package to bind `ts` with `beyonce` with `unnest_tokens` from the `tidytext` package to get one lyric per row per artist.\",\"Use `bind_log_odds` to figure out which words are more likely to come from a Taylor Swift or Beyonce song?\",\"Use `slice_max` from the `dplyr` package to select the top 100 words by `num_words_total` and then the top 25 by `log_odds_weighted`. Results are used to create a diverging bar chart showing which words are most common between Beyonce and Taylor Swift songs.\",\"Use `scale_x_continuous` to make the `log_odds_weighted` scale more interpretable.\",\"Take the previous plot and turn it into a `lollipop graph` with `geom_point(aes(size = num_words_total, color = direction))`\",\"Use `ifelse` to change the `1x` value on the x-axis to `same`.\",\"Create a `geom_point` with `geom_abline` to show the most popular words they use in common.\",\"Summary of screencast.\",\"Use `fct_relevel` from the `forcats` package to order the factor levels for the `tourney_finish` variable.\",\"Use `geom_tile` from the `ggplot2` package to create a `heatmap` to show how far a particular seed ends up going in the tournament.\",\"Use `scale_y_continuous` from the `ggplot2` package with `breaks = seq(1, 16)` in order to include all 16 seeds.\",\"Use `geom_text` from the `ggplot2` package with `label = percent(pct)` to apply the percentage to each tile in the heatmap.\",\"Use `scale_x_discrete` and `scale_y_continuous` both with `expand = c(0, 0)` to remove the space between the x and y axis and the heatmap tiles. David calls this flattening.\",\"Use `scale_y_reverse` to flip the order of the y-axis from 1-16 to 16-1.\",\"Use `cor` from the `stats` package to calculate the `correlation` between `seed` and `tourney_finish`. Then plotted to determine if there is a correlation over time.\",\"Use `geom_smooth` with `method = \\\"loess\\\"` to add a smoothing line with confidence bound to aid in seeing the trend between `seed` and `reg_percent`.\",\"Use `fct_lump` from the `forcats` package to lump together all the conference except for the `n` most frequent.\",\"Use `geom_jitter` from the `ggplot2` package instead of `geom_boxplot` to avoid overplotting which makes it easier to visualize the points that make up the distribution of the `seed` variable.\",\"Use `geom_smooth` with `method = \\\"lm\\\"` to aid in seeing the trend between `reg_percent` and `tourney_w`.\",\"Create a `dot pipe function` using `.` and `%>%` to avoid duplicating summary statistics with `summarize`.\",\"Use `glue` from the `glue` package to concatenate together `school` and `n_entries` on the `geo_col` y-axis.\",\"Summary of screencast.\",\"Use `pivot_wider` with `values_fill = list(value =0))` from the `tidyr` package along with `mutate(value = 1)` to pivot the `medal` variable from `long` to `wide` adding a 1 for the medal type awarded and 0 for the remaining medal types in the row.\",\"Use `fct_lump` from the `forcats` package to lump together all the beers except for the N most frequent.\",\"Use `str_to_upper` from the `stringr` package to convert the case of the `state` variable to uppercase.\",\"Use `fct_relevel` from the the `forcats` package in order to reorder the `medal` factor levels.\",\"Use `fct_reorder` from the `forcats` package to sort `beer_name` factor levels by sorting along `n`.\",\"Use `glue` from the `glue` package to concatenate `beer_name` and `brewery` on the y-axis.\",\"Use `ties.mthod = \\\"first\\\" ` within `fct_lump` to show only the first `brewery` when a tie exists between them.\",\"Use `setdiff` from the `dplyr` package and the `state.abb` built in vector from the `datasets` package to check which states are missing from the dataset.\",\"Use `summarize` from the `dplyr` package to calculate the `number of medals` with `n_medals = n()`, `number of beers` with `n_distinct`, `number of gold medals` with `sum()`, and `weighted medal totals` using `sum(as.integer()` because `medal` is an ordered factor, so 1 for each bronze, 2 for each silver, and 3 for each gold.\",\"Import `Craft Beers Dataset` from `Kaggle` using `read_csv` from the `readr` package.\",\"Use `inner_join` from the `dplyr` package to join together the 2 datasets from `kaggle`.\",\"Use `semi_join` from the `dplyr` package to join together to see if the beer names match with the `kaggle` dataset. Ends up at a dead end with not enough matches between the datasets.\",\"Use `bind_log_odds` from the `tidylo` package to show the representation of each beer category for each state compared to the categories across the other states.\",\"Use `complete` from the `tidyr` package in order to turn missing values into explicit missing values.\",\"Use `reorder_within` from the `tidytext` package and `scale_y_reordered` from the `tidytext` package in order to reorder the bars within each facet panel.\",\"Use `fct_reorder` from the `forcats` package to reorder the `facet panels` in descending order.\",\"For the previous plot, use `fill = log_odds_weighted > 0` in the `ggplot` `aes` argument to highlight the positive and negative values.\",\"Use `add_count` from the `dplyr` package to add a `year_total` variable which shows the total awards for each year. Then use this to calculate the percent change in totals medals per state using `mutate(pct_year = n / year)`\",\"Use `glm` from the `stats` package to create a `logistic regression` model to find out if their is a statistical trend in the probability of award success over time.\",\"Exapnd on the previous model by using the `broom` package to fit multiple `logistic regressions` across multiple states instead of doing it for an individual state at a time.\",\"Use `conf.int = TRUE` to add `confidence bounds` to the `logistic regression` output then use it to create a `TIE Fighter` plot to show which states become more or less frequent medal winners over time.\",\"Use the `state.name` dataset with `match` from `base r` to change state abbreviation to the state name.\",\"Summary of screencast.\",\"Use `fct_reorder` from the `forcats` package to reorder the factor levels for `category` sorted along `n`.\",\"Brief explanation of why `scale_x_log10` is needed given the distribution of `category` and `price` with `geom_boxplot`.\",\"Using `geom_jitter` with `geom_boxplot` to show how many items are within each `category`.\",\"Use `add_count` from the `dplyr` package and `glue` from the `glue` package to concatenate the `category` name with `category_total` on the `geom_boxplot` y-axis.\",\"Convert from `Saudi Riyals` to `United States Dollars`.\",\"Create a `ridgeplot` - AKA `joyplot` - using `ggridges` package showing the distribution of `price` across `category`.\",\"Discussion on `distributions` and when to use a `log scale`.\",\"Use `fct_lump` from the `forcats` package to lump together all the levels in `category` except for the `n` most frequent.\",\"Use `scale_fill_discrete` from the `ggplot2` package with `guide = guide_legend(reverse = TRUE)` to reverse the `fill legend`.\",\"Use `str_trim` from the `stringr` package to remove whitespace from the `short_description` variable. David then decides to use `str_replace_all` instead with the following regular expression `\\\"\\\\\\\\s+\\\", \\\" \\\"` to replace all whitespace with a single space instead.\",\"Use `separate` from the `tidyr` package with `extra = \\\"merge\\\"` and `fill = \\\"right\\\"` to separate item description from item dimension.\",\"Use `extract` from the `tidyr` package with the regular expression `\\\"[\\\\\\\\d\\\\\\\\-xX]+) cm\\\"` to extract the numbers before `cm`.\",\"Use `unite` from the `tidyr` package to paste together the `category` and `main_description` columns into a new column named `category_and_description`.\",\"Calculate the volume given the `depth`, `height`, and `width` of each item in dataset in liters using `depth * height * width / 1000`. At 36:15, David decides to change to `cubic meters` instead using `depth * height * width / 1000000`.\",\"Use `str_squish` from the `stringr` package to remove whitespace from the start to the end of the `short_description` variable.\",\"Use `lm` from the `stats` package to create a linear model on a `log, log scale` to predict the price of an item based on volume + category. David then uses `fct_relevel` to reorder the factor levels for `category` such that `tables & desks` is first (starting point) since it's the most frequent item in the category variable and it's price distribution is in the middle.\",\"Use the `broom` package to turn the model output into a coefficient / TIE fighter plot.\",\"Use `str_remove` from the `stringr` package to remove `category` from the start of the strings on the y-axis using the regular expression `\\\"^category\\\"`\",\"Summary of screencast.\",\"Use `bind_rows` from the `dplyr` package to combine the two data sets.\",\"Use `group = interaction(type, country)` within `ggplot` `aes()` to set the interaction `type` with every single `country` on one plot.\",\"Use `semi_join` from the `dplyr` package to join rows from `phones` with a match in `country_sizes`.\",\"Use `quantile` from the `stats` package within `summarize` to show the 25th, and 75th quantiles (interquartile range) on the plot.\",\"Import the `wdi` package (World Development Indicators from the World Bank) with `extra = TRUE` in order to get the `iso3c` code and `income` level for each country.\",\"Use `inner_join` from the `dplyr` package to join the `WDI` data with the `phones` data.\",\"Use `fct_relevel` from the `forcats` package to reorder `income` factor levels in ascending order.\",\"Create an `anonymous function` using `.` (dot).\",\"Use `inner_join` from the `dplyr` package to join the `mobile` data and `landline` data together with a `geom_abline` to see how different the total populations are between the two datasets.\",\"Use `geom_hline` to add a refrence line to the plot shwoing when each country crossed the 50 per 100 subscription mark.\",\"Use `summarize` from the `dplyr` package with `min(year([Mobile >= 50]))` to find the year in which each country crossed the 50 per 100 subscription mark.\",\"Use `summarize` from the `dplyr` package with `max(Mobile)` to find the peak number of mobile subscriptions per country.\",\"Use `na_if` from the `dplyr` package within `summarize` to change `Inf` to `NA`.\",\"Using the `WDIsearch` function to search the `WDI` package for proper GDP per capita indicator. Ended up using the `NY.GDP.PCAP.PP.KD` indicator.\",\"Adding the `GDP` data from the `WDI` package to the `country_incomes` table.\",\"Using the `inner_join` function from the `dplyr` package to join the `phones` table with the `country_incomes` table pulling in the `gdp_per_capita` variable.\",\"Using the `WDIsearch` function to search the `WDI` package for proper population indicator. Ended up using the `SP.POP.TOTL` indicator.\",\"Create an animated choropleth world map with `fill = subscriptions`.\",\"Summary of screencast\",\"Using `sample()` and `cumsum()` to simulate a random walk\",\"Using `%%` (modulo operator) to \\\"close\\\" the circle (set the number of people in the circle)\",\"Using `crossing` function to set up \\\"tidy\\\" simulation (gives you all possible combinations of values you provide it)\",\"Using `distinct` function and its `.keep_all` argument to get only the first unique set of the variables you give it\",\"Visualizing the number of steps it takes for the sauce to reach people at differents seats\",\"Visualizing the distribution of number of steps it takes to reach each seat\",\"Investigating the parabolic shape of average number of steps to reach a given seat\",\"Using `lm` and `I` functions to calculate formula of the parabola describing average number of steps\",\"Starting to vary the size of the table\",\"Summary of screencast\",\"Inspecting the dataset\",\"Using `geom_histogram` to look at distribution of obstacles in a stage\",\"Using `str_remove` function to clean stage names (remove \\\"(Regional/City)\\\")\",\"Asking, \\\"Are there obstacles that are more common in the Finals than Qualifying rounds?\\\"\",\"Using `bind_log_odds` function from `tidylo` package to calculate log-odds of obstacles within a stage type\",\"Using `unite` function to combine two columns\",\"Graphing the average position of different obstacles with many, many tweaks to make it look nice\",\"Creating a stacked bar plot of which obstacles appear in which order\",\"Turning stacked bar plot visualization into a custom function\",\"Asking, \\\"Is there data on how difficult an obstacle is?\\\"\",\"Visualizing which obstacles appear in different seasons with `geom_tile` and a lot of tweaking\",\"Reviewing the result of the previous step (obstacles in different seasons)\",\"Summary of screencast\",\"Use the `add_count` function from the `dplyr` package with `name = \\\"country_total\\\"` to count the number of observations by group in the `name` variable.\",\"Use `filter` from the `dplyr` package with `country_total == max(country_total)` to filter the data for countries where every data point is provided.\",\"Use the `rename` function from the `dplyr` package to rename the `name` variable to `country_name`.\",\"Use `theme(legend.position = \\\"none\\\")` to hide the legend generated by the `geom_line` plot.\",\"Use the `expand_limits` function from the `ggplot2` package with `y = 0` so that each `facet panel` has a y-axis that starts at the same point, in this case 0.\",\"Reorder `facet panels` using the `fct_reorder` from the `forcats` package with a function passed in to the `.fun` argument to calculate the ratio between `max` and `min` values in the `local_price` variable. At 12:00, David changes from using `max` and `min` to `last` and `first` to calculate the `Big Mac inflation rate`.\",\"Use `scale_x_log10` from the `ggplot2` package to change the `breaks` for the `x-axis` while also applying a `log10` tranformation.\",\"Use `geom_text` from the from the `ggplot2` with `paste0` package to add labels to each bar in the plot indicating how many time `X` the price of a Big Mac increased from 2000 to 2020.\",\"Add two lines to a plot using 2 `geom_line` with `color =` argument and `y=` argument to distinguish between the two lines.\",\"Use `geom_hline` from the `ggplot2` package to add horizontal reference line to each facet panel.\",\"Use `theme` from the `ggplot2` package with `axis.text.x = element_text(angle = 90, hjust = 1)` to rmake the x-axis labels horizontal in order to avoid overcrowding.\",\"Use `geom_text` to add country names to each point in `geom_point` plot. David then opts to use `geom_text_repel` from the `ggrepel` package instead to avoid overcrowding.\",\"Use `geom_smooth` from the `ggplot2` package with `lm` smoothing method to help show the linear trend when comparing `gdp_dollar` to `usd_raw`.\",\"Use the `gganimate` package to animate the `GDP per capital` versus `adjusted big mac index relative to USD` over time.\",\"Use `str_to_upper` and `str_remove` to remove `_adjusted` from `base_currency` while uppercasing the characters that remain.\",\"Use `pairwise_cor` from the `widyr` package to perform `pairwise correlation` to figure out which countries Big Mac prices tend to move together over time.\",\"Screencast summary.\",\"Using `countrycode` function from `countrycode` package to convert two-letter country codes to country names\",\"Using `geom_errorbarh` function to visualize start and end times of transit projects\",\"Using `fct_reorder` function to reorder lines by project midpoint year\",\"Using `as.numeric` to convert character field (real_cost) to proper numeric field\",\"Using `mutate_at` function to apply the same function (`as.numeric`) to multiple fields in one line of code\",\"Using `geom_boxplot` and `fct_lump` to visualize cost per kilometre by country as boxplots\",\"Using `glue` function from `glue` package to combine fields to make easy-to-read labels on a graph\",\"Splitting boxplots into whether they are railroads (rr) or not, using `factor` function and `fill` argument\",\"Investigating sources of missing data for Shanghai\",\"Using `geom_jitter` with `geom_boxplot` to show distribution of items within each group\",\"Setting `geom_boxplot` argument `outlier.size = -1` as a hack to get rid of boxplot-generated outlier points\",\"Starting to build a `shiny` app\",\"Review of preliminary `shiny` app\",\"Screencast summary\",\"Showing how to upload code to GitHub in RStudio\",\"Using `clean_names` to convert variable names from `camelcase` to `snakecase`.\",\"Use `fct_reorder` to reorder `geom_col` columns in ascending order.\",\"\\\"Use `extract` to extract a character column into multiple columns using the regular expression `\\\"\\\"(.*) on (.*)\\\"\\\"` at `6:05` David decides to change this to: Use `separate` with `sep = \\\"\\\" on \\\"\\\"` and `fill = \\\"\\\"left\\\"\\\"` and `extra = \\\"\\\"merge\\\"\\\"` to control what happens when there are not enoughor too many pieces. at `7:10` David decides to change to `fill = \\\"\\\"right\\\"\\\"`.\\\"\",\"Use `replace_na` to replace NAs with specified values. In this case replace them with `Missing`.\",\"\\\"Use `fct_lump` to lump `artist` and `medium` levels except for the n most frequent. at `11:30` David decides to use `filter(fct_lump(artist, 16) != \\\"\\\"Other\\\"\\\")` to get rid of the artist `Other` category. \\\"\",\"\\\"Create a `geom_area` plot to show the distribution of paintings by medium over time. At `15:35` David decides to change from count to percentage to make it easier to show the difference in composition using `mutate(pct = n / sum)`.\\\"\",\"Bucket `year` variable into decades using `round(year -1)` to round the year to the nearest 10.\",\"Use `scale_y_continuous(labels = scales::percent)` to change y-axis labels to percent format.\",\"Turn the `geom_area` plot into a faceted `geom_col`.\",\"\\\"Calculate the percentage of artists for each medium per decade. \\\"\",\"Calculate the distribution of the area (square meters) and ratio (width / height) of the art pieces.\",\"Categorize the pieces by shape(landscape, portait, scquare) based on their ratio then plot using `geom_area` to look at the composition over time.\",\"Craete a `line plot` showing the median ratio by decade over time.\",\"Craete a `line plot` showing the median area by decade over time.\",\"Create a `boxplot` showing the distribution of area over time.\",\"Create various `summary statistics` for the artists such as `avg_year`, first_year`, `last_year`, `n_pieces`, `median_area`, `median_ratio`.\",\"Create a `boxplot` showing the distribution of ratio over time for n amount of artists. Use `glue` to concatonate number of pieces for each artist ont he y axis.\",\"Create a `boxplot` showing the distribution of ratio over time for each medium. Use `glue` to concatonate number of pieces for each medium on the y axis.\",\"Summary of screencast\",\"Trim whitespace from a string.\",\"Reorder factor levels by sorting along another variable by sum.\",\"Label x axis numbers in decimal format (e.g. 0.12, 1,234).\",\"Pivot data from wide to long.\",\"Convert case of a string to title case.\",\"Add text labels to the `geom_point` plot.\",\"Add horizontal reference line to `geom_point` plot.\",\"Label y axis numbers in percent format.\",\"Expand the plot axis limits by having the y axis begin at 0.\",\"Position x axis data on a log10 scale.\",\"Pivot data from wide to long.\",\"Convert case of a string to title case.\",\"Reorder factor levels by sorting along another variable by sum.\",\"Create a heatmap.\",\"Complete a data frame with missing combinations of data.\",\"Rotate x axis labels 90 degrees.\",\"Join two datasets while including all rows in x or y.\",\"Replace matched patterns in a string using `str_replace_all` with the `regular expression` `([a-z])([A-Z])` and `\\\"\\\\\\\\1 \\\\\\\\2\\\"` to separate words that were joined together (e.g. TanaRiver, Tana River).\",\"Join two datasets while returning all rows from x without a match in y.\",\"Join two datasets while including all rows in y.\",\"Join two datasets while including all rows in x and y.\",\"Import and basic exploration of the `rKenyaCensus` package shapefiles.\",\"Create a map using the `rKenyaCensus` shapefile data.\",\"Simplify the shapefile data to make for faster processesing.\",\"Join two datasets while including all rows in x.\",\"Create a choropleth map - TROUBLSHOOTING through 41:45.\",\"Create a flexible function that generates `geom_col` plots used for for exploring the many different datasets in the `rKenyaCensus` package.\",\"Lump together factor levels into \\\"other\\\".\",\"Summary of screencast.\",\"Detect the presence or absence of a pattern in a string.\",\"Separate a character column into multiple columns with a regular expression or numeric locations\",\"Rename column.\",\"Select only unique/distinct rows from a data frame.\",\"Expand the y axis plot limits by starting at 0.\",\"Combine two datasets while including all rows in x and y.\",\"Y axis labels as percentages (2.5%, 50%, etc).\",\"Bind multiple data frames by row and an explanation as to why it's not the best approach for joining given the other options.\",\"Brief discussion on the differences between `rbind` and `row_bind`.\",\"Remove matched patterns in a string.\",\"Turn variable names into 'snake case' (e.g. Standard Error, standard_error).\",\"Mutate multiple columns to change type from `character` to `numeric` while parsing out the numbers while getting rid of the other characters in the dataset.\",\"Subset rows using their positions.\",\"Reshape the data from wide to long such that there is one row for each year and race.\",\"Compute the absolute value of x\",\"Remove matched patterns in a string (e.g. black1, black & white1, white).\",\"Reorder factor levels in `geom_line` plot by sorting along another variable.\",\"Bind multiple data frames by row.\",\"Reorder factor levels by hand.\",\"Detect and remove the presence of a pattern in a string to remove duplication from `geom_line` plot legend.\",\"\\\"Reorder factor levels in `geom_line` plot by sorting along another variable with ordering based on the last value to make the data line up with how the values are displayed in the legend. 'fct_reorder(race_ethnicity, percent, last, .desc = TRUE)`\\\"\",\"Import external Excel data set from `Data.World`.\",\"Select variables that match a pattern to remove.\",\"Unpack data in one column (field_gender) into two separate columns (field, gender).\",\"Summary of screencast.\",null],\"Functions\":[\"read_csv\",\"geom_histogram | geom_boxplot\",\"fct_reorder\",\"dollar_format\",\"geom_point\",\"str_to_title\",null,\"geom_text_repel\",\"count\",null,null,\"geom_col\",\"summarise_at\",\"geom_point\",\"geom_smooth\",null,\"geom_smooth\",\"lm\",\"nest | tidy\",\"p.adjust\",null,\"fct_lump\",null,\"ggplotly\",null,\"parse_date\",\"fct_lump\",null,\"problems\",\"arrange | distinct\",\"goem_boxplot\",\"floor\",\"summarise_at\",\"geom_line\",\"facet_wrap\",null,\"paste0\",null,null,\"paste0\",\"geom_text\",\"ggplotly\",null,\"geom_line\",null,null,null,\"countrycode\",\"fct_lump\",\"hour\",\"facet_wrap\",null,\"as.POSIXlt\",\"lag\",\"as.numeric\",null,\"scale_x_log10\",null,null,\"cran_downloads\",\"count\",\"geom_point\",\"coord_map\",\"borders\",\"fct_lump\",null,null,\"ifelse\",null,null,\"mutate_if\",null,null,null,\"is.infinite\",\"crossing\",null,null,null,null,\"geom_line\",\"geom_point\",\"borders\",\"scale_colour_gradient2\",\"arrange\",\"%/%\",null,\"sample | unique\",\"last\",null,\"anti_join\",null,\"geom_polygon | theme_void | coord_map\",null,\"facet_wrap\",null,null,\"regex_inner_join\",\"str_remove\",null,null,\"countrycode\",null,null,null,null,null,null,null,\"qbeta\",null,\"geom_ribbon\",\"starts_with\",\"gather\",\"str_remove\",null,\"fct_reorder\",\"n_distinct\",null,\"parse_number\",null,null,null,\"add_ebb_estimate\",null,\"pairwise_cor\",null,\"geom_node_text\",\"theme_void\",null,null,\"geom_node_text\",null,null,\"geom_line\",\"%/%\",null,\"percent_format\",\"geom_col\",\"replace_na\",null,\"comma_format\",\"cut\",null,\"scale_colour_gradient2\",\"scale_colour_gradient2\",\"str_to_title\",\"glm\",null,\"augment\",\"augment\",null,null,null,null,\"geom_vline\",\"tidy | geom_errorbarh\",null,null,\"summarise_at | starts_with\",\"gather\",null,\"median\",null,\"pmin\",\"scale_x_continuous\",null,null,\"unnest_tokens\",\"anti_join\",\"str_detect\",null,null,null,\"pairwise_cor\",null,\"geom_node_text\",null,null,\"scale_colour_gradient2\",null,null,\"cast_sparse\",null,\"cv.glmnet\",null,null,\"tidy\",null,null,\"crossing\",null,\"sample\",\"group_by | summarise\",null,null,\"unnest | seq_len\",null,\"seq\",null,null,null,null,\"approx\",null,null,\"matrix\",null,\"sample\",null,null,null,null,null,null,\"all\",null,\"rerun | map_lgl\",null,\"cumsum | lag\",null,null,null,null,null,null,null,null,null,null,null,null,null,\"separate\",\"distinct\",\"nest | t.test\",null,null,null,\"cut\",null,\"semi_join\",null,\"pairwise_cor\",\"widely_svd\",\"widely_svd\",\"widely_svd\",null,\"str_sub\",null,\"crossing\",\"rbinom\",\"ifelse\",null,null,\"group_by | ifelse | row_number\",\"case_when\",\"cumsum\",null,null,null,null,null,\"count | fct_lump\",null,null,null,\"geom_area\",\"%/%\",\"complete\",\"fct_reorder\",\"geom_vline\",null,\"regex_left_join\",\"distinct\",\"coalesce\",null,\"survfit\",null,null,null,\"tidy\",null,null,null,null,null,null,\"floor_date\",null,\"contains\",null,null,\"unnest_tokens\",\"anti_join\",null,null,null,null,\"floor_date\",null,\"bind_tf_idf\",\"top_n\",\"str_detect\",\"distinct\",null,\"geom_text\",\"geom_text_repel\",null,null,null,null,\"str_detect\",\"str_count\",null,\"geom_text\",null,null,null,null,\"%in% | all\",null,\"facet_wrap\",null,null,\"%/%\",\"mutate\",\"gather\",\"pmin\",null,\"paste0 | spread\",\"distinct\",\"glm\",\"ntile | cut\",null,null,\"augment\",\"crossing\",null,null,\"str_detect\",null,\"fct_collapse\",\"countrycode\",null,\"geom_line\",\"fct_reorder\",\"geom_col\",\"%/%\",\"complete\",\"facet_wrap\",\"semi_join\",\"geom_point\",null,\"geom_jitter\",null,null,\"facet_wrap\",null,null,\"any\",\"cut\",null,\"match\",null,\"str_remove\",null,null,\"%%\",\"scale_fill_gradient2\",\"summarise_at\",null,null,null,null,\"str_to_title | str_replace_all\",null,\"separate\",\"coalesce\",null,\"fct_lump\",\"facet_wrap\",null,null,\"tk_ts\",null,null,null,\"sw_glance\",\"sw_augment\",null,\"Arima\",\"sw_sweep | forecast\",\"geom_ribbon\",null,\"crossing\",\"invoke\",\"scale_linetype_discrete\",\"gather\",\"fct_recode\",null,null,\"read_xlsx\",null,\"gather\",\"fill\",\"fill | ifelse\",\"spread\",\"str_detect\",\"sample\",null,null,null,null,null,\"contains\",\"fct_recode\",null,\"setdiff\",\"fct_lump\",null,\"fct_reorder | length\",\"fct_infreq\",\"fct_lump\",\"scale_fill_gradient2\",null,\"sprintf\",\"summarise_at\",\"geom_tile\",\"fill\",\"paste0\",null,null,null,null,\"complete.cases\",null,null,null,\"scale_colour_gradient2\",\"ggplotly\",null,null,null,null,null,null,\"scale_x_log10\",\"geom_histogram\",\"separate_rows\",\"top_n\",\"facet_wrap\",\"lm\",null,null,null,null,null,\"geom_boxplot\",\"unite\",null,null,null,\"setdiff\",null,\"glmnet\",\"cv.glmnet\",null,\"unite\",null,null,null,\"mdy\",\"geom_col\",\"facet_wrap\",null,\"add_count\",null,null,null,null,null,\"phyper\",null,null,null,\"complete\",null,\"p.adjust\",\"p.adjust\",null,null,\"crossing\",null,null,\"transmute\",\"kable\",null,null,\"summarise_all | summarise_at\",null,\"between\",null,null,\"as.difftime\",null,null,\"wday\",\"spread\",null,null,null,\"mutate\",null,\"add_count | fct_reorder\",\"str_to_title | str_replace\",\"inner_join\",\"difftime | as.numeric\",null,null,\"%/%\",\"interaction\",null,null,null,\"row_number\",\"cumsum\",\"lag\",null,null,null,null,\"match\",\"cummean\",null,null,\"gather\",null,null,null,null,null,null,null,null,null,\"complete\",\"slice\",null,\"geom_text\",\"WDIsearch\",null,\"comma_format\",null,\"spread | pivot_wider\",\"to_snake_case\",null,null,\"lm\",null,null,\"aov\",null,\"cor\",null,\"geom_col | %/%\",\"n_distinct\",\"distinct\",\"coalesce\",\"year\",\"fct_reorder\",\"count\",\"geom_col | facet_wrap\",\"WDIsearch\",\"fct_relevel\",null,\"mean\",\"rank\",\"geom_histogram\",null,null,\"summarise_all\",\"geom_text\",\"pmin\",null,null,null,\"regex_left_join\",\"coord_fixed\",null,null,null,\"extract\",\"extract\",null,\"fct_lump | fct_relevel\",null,null,\"tidy\",\"str_replace\",\"augment\",null,null,null,\"pairwise_cor\",\"cast_sparse\",null,null,null,null,\"tidy\",null,null,null,null,null,null,null,null,null,\"str_trunc\",null,\"gather\",null,\"fct_lump\",\"reorder_within\",\"lm\",null,\"fct_relevel\",\"extract\",\"facet_wrap\",\"geom_vline\",\"unnest_tokens\",null,null,\"read_html | html_node | html_table\",\"clean_names\",null,\"parse_number\",null,\"html_nodes | html_text | str_subset\",\"message\",\"unnest_tokens | anti_join\",null,\"str_detect\",\"str_remove\",\"possibly | safely\",null,\"pairwise_cor\",null,\"geom_node_text\",null,null,null,null,\"semi_join\",null,\"glue\",\"fct_reorder\",null,null,\"geom_text\",null,null,\"fct_reorder\",\"geom_tile\",\"scale_fill_gradient2\",null,\"fct_rev\",null,null,null,\"paste0\",\"expand_limits\",null,null,null,null,\"rev\",\"geom_smooth\",\"geom_abline\",null,\"glue\",\"clean_names\",\"gather\",\"str_to_title | str_replace\",\"str_remove_all\",\"extract\",\"add_count\",null,null,null,\"pairwise_cor\",null,null,null,null,null,null,\"acast\",\"t | colSums | colMeans\",\"svd\",null,\"reorder_within\",null,null,null,\"str_detect\",\"separate_rows\",\"parse_number\",null,\"semi_join\",\"anti_join\",\"ifelse\",null,\"sample\",\"geom_histogram\",\"unnest_tokens | anti_join\",\"bind_tf_idf\",\"top_n\",\"paste0\",null,null,null,\"fct_relevel\",null,null,\"fct_reorder\",\"glue\",null,\"t.test\",null,\"rep\",null,\"geom_errorbarh\",null,null,null,null,null,null,null,\"geom_abline\",null,\"select | sort | colnames\",\"geom_abline\",\"geom_boxplot\",null,\"sample_frac\",\"geom_smooth\",\"augment\",null,null,null,null,\"unnest\",null,\"glance\",null,null,\"floor\",\"summarise_at\",\"extract\",\"parse_number\",null,null,\"pull\",null,\"separate_rows\",\"separate\",null,null,null,null,null,null,null,null,null,null,null,\"unite\",null,\"geom_point\",null,null,null,null,null,null,null,\"summarise_at\",null,\"get_map\",null,null,\"read_sf\",\"geom_sf\",null,null,null,\"ends_with | gather\",null,null,null,null,null,null,null,null,null,null,null,null,\"gather\",\"facet_wrap\",\"reorder_within\",\"geom_text\",null,\"str_extract\",\"guides\",null,null,null,\"separate_rows\",\"extract\",null,\"read_lines\",\"str_detect\",\"str_split\",\"setdiff\",null,\"n_distinct\",\"map\",\"acast\",null,\"%*%\",\"microbenchmark\",\"combn\",\"map\",\"which.max\",\"t\",null,null,null,\"fct_inorder\",\"theme | element_text\",\"geom_line | geom_point\",null,\"theme | element_blank\",\"geom_text_repel\",\"row_number\",null,\"unnest_tokens\",\"anti_join\",\"str_remove_all\",\"bind_tf_idf\",\"reorder_within | scale_x_reordered\",null,null,\"str_remove\",\"str_to_lower\",null,\"separate_rows\",\"log2\",\"cast_sparse\",\"semi_join\",null,\"cv.glmnet\",null,null,null,null,null,null,\"dir\",null,\"hoist\",\"hoist\",\"pluck\",\"object.size\",\"map_chr | str_c\",\"unnest_tokens\",null,null,null,\"tokenize_words\",\"unnest_tokens\",\"sample_n\",null,\"pairwise_cor\",null,null,\"unnest_wider\",\"str_trunc\",\"glue\",null,null,null,null,\"use_data_raw\",null,\"use_package\",null,null,null,\"use_data\",null,\"load_all\",\"document\",null,\"use_data\",null,null,null,null,null,\"use_readme_rmd\",\"knit\",null,null,null,null,\"accumulate\",null,\"~\",null,null,\"accumulate\",null,\"accumulate\",null,\"replicate\",\"qplot\",null,null,\"table | sort\",null,\"crossing\",\"map_dbl\",null,\"lm\",null,null,null,\"filter | max\",\"paste | ymd\",null,null,\"install_github\",\"cross_by_dimensions\",\"cross_by_periods\",\"use_metrics_scaffold\",\"create_metrics\",\"preview_metrics\",null,null,\"parse_number | fct_lump | coalesce\",null,null,\"match\",\"geom_sf\",\"theme_map\",null,null,null,null,null,null,\"accumulate\",\"sample\",null,\"cumsum\",\"lag\",\"cummax | lag\",\"cummin\",null,\"row_number\",null,\"seq | scale_x_continuous\",null,\"%/%\",null,\"transmute\",\"survfit\",\"glance\",\"extract\",null,\"group_by\",\"rank | percent_rank\",\"geom_smooth\",\"cut\",null,null,null,\"reorder_within\",null,null,null,\"rexp\",\"rexp\",null,\"which\",\"replicate\",null,\"crossing\",null,null,\"nls\",null,\"augment\",null,null,null,null,null,\"mdy\",\"rename\",\"fct_reorder\",\"fct_lump | count\",\"scale_x_continuous\",\"month\",\"na_if\",\"fct_reorder\",\"dollar\",\"str_trunc\",\"separate_rows\",\"extract\",\"geom_jitter\",\"inner_join\",\"paste0\",\"str_detect\",\"group_by | summarize | geom_point\",\"ggplot2\",\"preview_metric\",\"cross_by_dimensions | cross_by_periods | use_metrics_scaffold | create_metrics\",\"rename | cross_by_periods\",\"cross_by_periods\",\"use_metrics_scaffold | create_metrics\",\"str_remove\",\"cross_by_dimensions\",null,\"crossing\",\"rbinom\",\"dbinom\",\"map_dbl\",\"seq_len\",\"optimise\",null,null,\"map2_dbl\",null,null,null,\"optimise\",\"unnest_wider\",null,null,null,\"floor_date\",\"unnest_tokens | anti_join\",null,\"geom_line\",\"mean\",\"geom_text\",null,null,\"stm\",\"stm\",null,null,\"tidy\",null,\"str_sub\",\"str_replace | map2\",null,\"cor\",null,\"mutate\",\"str_detect\",\"grom_point | theme_map | borders\",\"fct_lump\",\"str_remove\",\"leaflet | addTiles | addCircleMarkers\",\"glue\",\"gather | nest | map\",\"str_replace | str_to_title\",\"kable\",\"paste0\",\"replace_na\",\"addMeasure\",\"colorNumeric\",\"transition_time | frame_time\",\"geom_point\",\"scale_size_continuous\",\"scale_color_gradient2\",\"transition_reveal\",\"pivot_longer\",\"mutate_at\",\"separate\",\"rename\",\"pivot_wider\",\"str_to_upper\",\"row_number\",\"separate_rows\",\"separate\",\"na_if\",\"str_remove\",\"mutate | group_by | summarize\",\"summarize\",\"type_convert\",\"summarize_all\",\"summarize | inner_join | geom_point | glm |cbind\",\"summarize | year\",null,null,\"fct_reorder\",\"fct_lump\",\"pairwise_cor\",\"reorder_within | scale_x_reordered\",\"graph_from_data_frame | ggraph | geom_edge_link | geom_node_point | geom_node_label\",\"extract\",\"extract\",\"replace_na\",\"geom_text_repel\",\"na_if\",\"scale_size_continuous\",\"graph_from_data_frame | geom_node_point\",\"widely_svd | top_n | abs | geom_col | reorder_within | scale_y_reordered | facet_wrap\",\"paste0\",null,\"fct_reorder\",\"str_remove\",\"str_trim\",\"ggplotly\",\"ylim\",\"paste0\",\"aes\",\"tooltip\",\"glue\",\"separate_rows\",\"str_to_title\",\"str_detect\",\"read_html | html_nodes | html_table | setNames\",\"map | possibly | read_html\",null,\"fct_lump\",\"fct_reorder\",\"geom_vline\",\"count\",\"str_trunc\",\"theme\",\"ggraph | geom_edge_link | geom_node_point | geom_node_text\",\"arrow\",\"scale_edge_size_continuous\",\"summarize | mean\",\"geom_col | facet_wrap\",\"wordcloud | geom_text_wordcloud\",\"fct_recode\",\"reorder_within\",null,\"summarize | across\",\"ggplot | borders\",\"read_sf\",\"min | max\",\"sample | geom_path\",\"as.Date | floor_date\",\"difftime | lag\",\"distHaversine | cbind\",null,\"separate\",\"summarize | across\",\"geom_col | fct_reorder\",\"geom_point | geom_text | geom_text_repel | \\nsummarize\",\"geom_point | geom_text | geom_text_repel | \\nsummarize\",\"geom_point | geom_text | geom_text_repel | \\nsummarize\",\"geom_point | pivot_longer | fct_reorder\",\"geom_point | geom_text | geom_text_repel | \\nsummarize\",\"geom_point | fct_reorder | geom_errorbarh\",\"summarize | group_by | arrange\",\"summarize | fct_lump\",\"summarize | fct_lump\",\"geom_line | summarize\",\"geom_col | summarize | fct_lump | facet_wrap\",null,\"count | mutate | fct_lump\",\"geom_boxplot\",\"geom_histogram\",\"fct_reorder\",\"summarize | across\",\"geom_col | fct_lump\",\"pivot_longer\",\"geom_line\",\"geom_density_ridges\",\"summarize\",\"pairwise_cor\",\"graph_from_data_frame | ggraph | geom_edge_link | geom_node_point | geom_node_text\",\"widely_svd | geom_col | reorder_within | scale_y_reordered\",\"geom_histogram\",\"pmin\",\"geom_point | geom_smooth\",\"summarize | cor\",\"lm | geom_point | tidy | map | geom_errorbarh\",null,\"use_tidytemplate\",\"rename\",\"fct_reorder\",\"fct_lump\",\"fct_recode\",\"fct_reorder\",\"scale_y_continuous\",\"complete\",\"max\",\"pivot_longer\",\"read_html | html_nodes | map |\",\"str_to_upper\",\"parse_number\",\"bind_rows\",\"inner_join\",\"mutate\",\"summarize\",\"scale_y_continuous\",\"read_sf | geom_sf | sf_simplify\",\"transition_manual\",null,\"pivot_longer | geom_histogram | facet_wrap\",\"geom_density | facet_wrap\",\"geom_boxplot | facet_wrap\",\"geom_bar\",\"geom_bar\",\"initital_split | training | logistic_reg | set_engine |\\nfit | fct_lump | predict | metrics | vfold_cv | \\nfit_resamples | collect_metrics | \\n\",\"initital_split | training | logistic_reg | set_engine |\\nfit | fct_lump | predict | metrics | vfold_cv | \\nfit_resamples | collect_metrics | \\n\",\"nearest_neighbor | initital_split | training | logistic_reg |\\nset_engine | fit | fct_lump | predict | metrics | vfold_cv | \\nfit_resamples | collect_metrics\",\"testing | predict | metrics\",\"decision_tree | set_engine\",\"multinom_reg | set_engine | fit_resamples\",null,\"count\",\"pivot_longer | gather\",\"as.integer\",\"fct_reorder\",\"scale_y_continuous | comma\",\"replace_na\",\"fct_lump\",\"reorder_within | scale_y_reordered\",\"geom_flag\",\"fct_recode\",\"ifelse\",\"str_to_lower\",\"geom_point | geom_line | \\nscale_y_log10 | geom_flag\",\"scale_x_continuous\",\"scale_x_continuous | geom_text\",\"function\",null,\"count | fct_lump | fct_reorder\",\"fct_relevel\",\"fct_reorder\",\"reorder_within | scale_y_reordered\",\"axis.text.x\",\"filter | fct_lump\",\"separate\",\"fct_lump\",\"read_html | html_nodes | html_text \\n\",\"str_trim\",\"separate\",\"read_html | html_nodes | html_text \\nhtml_attr | inner_join | paste0 | map\",null,\"geom_histogram\",\"geom_point | geom_line\",\"group_by | summarize\",\"geom_line | geom_point\",\"fct_reorder\",\"gnemonol | arrange\",\"pivot_longer | separate_rows\",\"fct_lump | fct_reorder\",\"geom_col\",\"fct_relevel\",\"fct_rev | scale_fill_discrete\",\"add_count | distinct | pairwise_cor\",\"ggraph | geom_edge_link | geom_node_point | geom_node_text\",\"pairwise_count\",\"unite | pairwise_count\",\"summarize | min | mean | max\",\"slice | tail\",\"semi_join | geom_boxplot | fct_reorder\",\"pivot_wider | lm | linear_reg | set_engine | fit | initial_split | training | plot | base | vfold_cv | fit_resamples | tune_grid | collect_metrics | geom_line | tidy | rand_forest | clean_names | step_ns | tune_grid | collect_metrics | prep | juice\",null,\"rename\",\"rename_all | str_remove\",\"pivot_longer\",\"geom_line | facet_wrap\",\"fct_reorder\",\"write_rds | inputPanel | renderPlot\",\"geom_line\",\"geom_point | geom_abline\",\"geom_boxplot\",\"geom_col\",\"geom_point | geom_text_repel\",\"countrycode | geom_hline | geom_text_repel\",null,\"count\",\"geom_col | fct_reorder\",\"semi_join\",\"unite | inner_join | glue | fct_reorder\",\"geom_point | as.integer | geom_text | geom_line\",\"geom_point | as.integer | geom_text | geom_line\",\"semi_join | geom_boxplot | coord_flip | fct_reorder | complete | fill | scale_x_log10\",\"semi_join | summarize | add_count | geom_boxplot | geom_smooth | geom_point\",\"spread | across | semi_join | lm | aov\",\"unnest_tokens | anti_join | bind_log_odds | semi_join | geom_col | scale_y_reordered\",\"unite | semi_join | pairwise_corr\",null,\"geom_line | summarize | unique | sample | facet_wrap | fct_reorder | theme_tufte | geom_vline\",\"geom_line | summarize | unique | sample | facet_wrap | fct_reorder | theme_tufte | geom_vline | geom_hline\",\"function\",\"function\",\"dir | map_df | function | set_names | pivot_longer | separate | extract\",\"read_xlsx\",\"geom_col | fct_reorder | scale_fill_discrete\",\"pairwise_corr | fct_reorder\",\"pivot_wider | geom_point |geom_text\",null,\"ggplot | fct_reorder\",\"summarize | across | arrange | mutate | inner_join\",null,null,\"add_ebb_estimate | geom_point | geom_abline\",\"ggplot | fct_reorder | geom_errorbarh\",\"geom_point\",\"mutate | case_when | str_detect |fct_lump | fct_reorder\",\"geom_histogram | geom_density\",\"geom_histogram\",\"mutate | pmax | geom_line | geom_point\",\"function\",\"mutate | pmax | geom_line | geom_point\",\"mutate | pmax | geom_line | geom_point\",\"fct_lump | glm | format.pval\",\"group_by | summarize\",\"geom_point | geom_errorbarh | conf.int\",null,\"fct_reorder\",\"labels\",\"rename_all | str_to_lower\",\"unnest_tokens\",\"anti_join\",\"bind_tf_idf\",\"reorder_within | scale_y_reordered | slice_max\",\"bind_log_odds\",\"filter | str_length\",\"distinct | mdy | str_remove\",\"inner_join | fct_recode\",\"fct_reorder | geom_col\",\"bind_rows | unnest_tokens\",\"bind_log_odds\",\"slice_max | geom_col | ifelse | fct_reorder\",\"scale_x_continuous\",\"geom_col | geom_point | geom_vline\",\"ifelse\",\"pivot_wider | clean_names | geom_abline | geom_point | slice_max | scale_y_log_10 | scale_x_log_10 | geom_text\",null,\"fct_relevel\",\"geom_tile | scale_fill_gradient2\",\"scale_y_continuous\",\"geom_text | scales\",\"scale_x_discrete | scale_y_continuous\",\"scale_y_reverse\",\"cor | geom_line\",\"geom_smooth\",\"fct_lump\",\"geom_jitter\",\"geom_smooth\",\". | %>%\",\"glue\",null,\"pivot_wider\",\"fct_lump\",\"str_to_upper\",\"fct_relevel\",\"fct_reorder\",\"glue\",\"fct_lump\",\"state.abb | setdiff\",\"summarize\",\"read_csv\",\"inner_join\",\"semi_join\",\"bind_log_odds\",\"complete\",\"reorder_within | scale_y_reordered | facet_wrap\",\"fct_reorder\",\"fill\",\"add_count | mutate\",\"glm | cbind\",\"group_by | summarize | list | glm|mutate | map\",\"conf.int\",\"state.name | match\",null,\"fct_reorder\",\"scale_x_log_10 | geom_boxplot\",\"geom_jitter | geom_boxplot\",\"glue | add_count\",\"mutate\",\"geom_density_ridges\",null,\"fct_lump\",\"scale_fill_discrete\",\"str_trim | str_replace_all\",\"separate\",\"extract\",\"unite\",\"mutate\",\"str_squish\",\"lm\",\"tidy | geom_point | geom_errorbarh | geom_vline\",\"str_remove\",null,\"bind_rows\",\"ggplot | group\",\"semi_join | top_n\",\"quantile | geom_ribbon\",\"WDI | select\",\"inner_join\",\"fct_relevel\",\".\",\"inner_join | geom_abline\",\"geom_hline\",\"summarize | min\",\"summarize | max\",\"na_if | summarize\",\"WDIsearch\",\"WDI | select\",\"inner_join\",\"WDIsearch\",\"map_data | iso3166 | regex_left_join | left_join | transition_manual\",null,\"sample | cumsum\",\"%%\",\"crossing\",\"distinct\",null,null,null,\"lm | I\",null,null,null,\"geom_histogram\",\"str_remove\",null,\"bind_log_odds\",\"unite\",null,null,null,null,\"geom_tile\",null,null,\"add_count\",\"filter | max\",\"rename\",\"theme\",\"expand_limits\",\"fct_reorder\",\"scale_x_log10\",\"geom_text | paste0\",\"geom_line\",\"geom_hline\",\"theme\",\"geom_text | geom_text_repel\",\"geom_smooth\",\"transition_manual | transition_time\",\"str_to_upper | str_remove\",\"pairwise_cor\",null,\"countrycode\",\"geom_errorbarh\",\"fct_reorder\",\"as.numeric\",\"mutate_at\",\"geom_boxplot | fct_lump\",\"glue\",\"factor\",null,\"geom_jitter\",\"geom_boxplot\",null,null,null,null,\"clean_names\",\"fct_reorder | geom_col\",\"extract | separate\",\"replace_na\",\"fct_lump | filter\",\"geom_area\",\"count | round\",\"scale_y_continuous\",\"facet_wrap | geom_col\",\"mutate | group_by | summarize | complete\",\"filter | mutate | ggplot | geom_histogram | scale_x_log10 | geom_vline\",\"mutate | case_when | geom_area | complete\",\"group_by | summarize | filter | ggplot | geom_line | geom_point\",\"group_by | summarize | filter | ggplot | geom_line | geom_point\",\"mutate | filter | ggplot | geom_boxplot | scale_y_log10\",\"group_by | summarize | arrange\",\"filter | add_count | mutate | ggplot | geom_boxplot | scale_x_log10 | geom_vline | glue\",\"filter | add_count | mutate | ggplot | geom_boxplot | scale_x_log10 | geom_vline | glue\",null,\"str_trim\",\"fct_reorder\",\"comma | scale_x_continuous\",\"gather\",\"str_to_title\",\"geom_text\",\"geom_hline\",\"comma | scale_y_continuous\",\"expand_limits\",\"scale_x_log10\",\"gather\",\"str_to_title\",\"fct_reorder\",\"geom_tile\",\"complete\",\"theme\",\"full_join\",\"str_replace_all\",\"anti_join\",\"right_join\",\"inner_join\",\"KenyaCounties_SHP\",\"st_as_sf | geom_sf\",\"st_simplify\",\"left_join\",\"ggplot | geom_sf | theme_map\",\"filter | gather | mutate | group_by | summarize | spread | select\",\"fct_lump\",null,\"str_detect\",\"separate\",\"rename\",\"distinct\",\"expand_limits\",\"full_join\",\"percent\",\"bind_rows\",\"rbind | row_bind\",\"str_remove\",\"clean_names\",\"mutate_if | is.character | parse_number\",\"slice\",\"gather | mutate | ifelse | str_remove | spread\",\"abs\",\"str_remove\",\"fct_reorder\",\"bind_rows\",\"fct_relevel\",\"str_remove\",\"fct_reorder\",\"read_excel\",\"starts_with\",\"str_remove | group_by | first | ifelse | cumsum\",null,null]},\"columns\":[{\"accessor\":\".details\",\"name\":\"\",\"type\":\"NULL\",\"sortable\":false,\"resizable\":false,\"filterable\":false,\"width\":45,\"align\":\"center\",\"details\":[{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=1065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=1245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=1305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=1800&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2415&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=2995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=3070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=3365&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=3485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=3890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=4140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=4205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=4250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nx5yhXAQLxw?start=4555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=1970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=2480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=2755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=3105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=3205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=3490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/3-DRwg9yeNA?start=3655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=1040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=1230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=1340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=1860&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2285&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=2860&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=3135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nms9F-XubJU?start=3475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=855&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=1180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=1995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=2280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=2740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=2820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=2935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=3405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=3475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=3705&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=3875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/O1oDIQV6VKU?start=3940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=1975&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2145&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/5_6O2oDy5Jk?start=3835&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1075&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1725&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1825&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=1970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=2945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rxJZT0duwfU?start=3605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=1195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=1295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=1635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=1745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=1875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=2070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=2220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=2300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=2755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=2915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3735&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=3935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/kzM-4jMh9Qs?start=4150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=415&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=725&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1355&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=1830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2865&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=2995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=3065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=3155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=3275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/C69QyycHsgE?start=3620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=735&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=835&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=905&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1355&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1705&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=1945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=2990&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pBGMt28xgvk?start=3960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=1725&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=2025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=2565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3330&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/em4FXPf4H-Y?start=3840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=80&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=330&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TDzd73z8thU?start=1030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=510&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=1990&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=2400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=2785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=2910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KiqpX-gNIS4?start=3610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=80&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=775&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=1065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=1100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=1520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=1820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=1890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=2790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=3060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=3395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=3555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=3645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=3835&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=4045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=4125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=4340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KE9ItC3doEU?start=4500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=145&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=1225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=1250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=1430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=1700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=1890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=2915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/oYGi2wgSJaM?start=3975&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=1005&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=1095&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=1150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=1265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=1920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=2880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=3090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZyPrP_Yo1BA?start=3395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=855&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=1120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=1455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=1580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=1985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=2010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=2470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=2540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=2625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=2895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=3010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=3290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/78kv808ZU6o?start=3425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=950&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1330&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1670&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=1930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=2855&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=3085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=3125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=3360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/13iG_HkEPVc?start=3440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1145&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=1690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=2130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/KzRP40PzopY?start=2380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=865&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=990&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=1065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=1125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=1720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=2090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=2375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=2705&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=3035&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=3100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=3140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bmaigtpKyiM?start=3210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=1070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=1525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=1800&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=2000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=2090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=2595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=2875&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/fv9SQ4IFNr4?start=3245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=955&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=975&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1505&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=1850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=2915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=3095&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=3315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=3525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=3655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/qirKGdQvy9U?start=3675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1075&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=2960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=3000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EF4A4OtQprg?start=3235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=1185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=1365&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=1590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=2625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=2730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=3015&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=3170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sBho2GJE5lc?start=3290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1215&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=1820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=2940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=3105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=3175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=3260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/YWUCUfEeNJI?start=3850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=1245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=1395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=1740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=1920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=2310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=2655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/zjWm__nFLXI?start=2805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1545&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=1935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=2910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=3110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=3150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=3270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=3440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=3480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=4010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=4080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NoUHdrailxA?start=4210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=1010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=1370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=1420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=1575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=2025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=2185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=2665&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=2955&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=3910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=4005&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yWSpLfmES7w?start=4220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=1010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=1305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=1740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=1770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=1920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=2025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=2175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=2370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BRdLOYtJk9o?start=3180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1020&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1665&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=1935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=2985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3510&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3735&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=3810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=4095&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=4230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=4650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AQzZNIyjyWM?start=4830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=335&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1865&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=1960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=2050&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=2265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=2880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/tCa2di7aEP4?start=3555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=1790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2015&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=2845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=3020&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=3095&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1xsbTs9-a50?start=3225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=1590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=2400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ZOQSuapvHqA?start=4185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1335&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2075&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2215&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=2880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=3410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/sD993H5FBIY?start=3465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=1085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=1250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=1580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=1885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2335&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=2890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EYuuAGDeGrQ?start=3400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=285&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=545&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1335&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=1880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=2190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=2385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=2475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=2535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=2715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=3315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=3480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=3555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Mkac8DHScps?start=3750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1800&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=1910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2865&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=2910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=3310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/RpeioixHOHw?start=3400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=1750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=2225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=2470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=2555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/yFRSTlk3kRQ?start=2745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=990&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=1965&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=2915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=3090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=3190&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=3410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6GV9sAD6Pi0?start=3500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=1200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=1575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=2040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=2160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=2585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=3280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=3470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=3525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dr4qw8o0nYU?start=3935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=1045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=1555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=1670&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=1795&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=2525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=2615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=2715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=3910&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/wFZhuQEfEYA?start=4755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=145&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=250&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=355&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=1150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=1210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=1345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=1540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=1945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=2225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=2275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=2485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=2565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3505&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=3955&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=4165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/_IvAubTDQME?start=4255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=55&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=640&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=1940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=2220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=2385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=2605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=2670&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=2740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=3125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=3210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=3570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=3985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-5HYdBq_PTM?start=4755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=70&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=510&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=1940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=2390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=2850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=3475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=3570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=3780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/F4oUJp76KUY?start=4945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=70&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=90&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=175&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/rUK9Wz9B2n0?start=485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=45&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=1000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=1040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/XEsNpxl5b1M?start=1080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=925&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=1705&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=2050&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=2485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=2805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=2935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3340&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3505&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=3940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=4010&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/1R4X09w7tQ8?start=4150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/aR6jf6ZzlFk?start=985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=1310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=1445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=1530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=1650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=1860&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=2070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=2475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=2525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=2870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=2890&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=3025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=3090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=3360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=3500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vT-DElIaKtE?start=3760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=35&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=795&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1385&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1430&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=1855&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=2325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/QtThluGted0?start=2760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=335&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=665&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=1055&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=1650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=1975&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=2328&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=2425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=2474&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=2575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EVvnnWKO_4w?start=2845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=1310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=1500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=1520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/OhY5ZaILRpg?start=2485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=740&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=855&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=990&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1205&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1365&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/nmS3UZSWYRo?start=1785&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=1350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=1845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2215&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=2900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=3120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=3235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Xt7ACiedRRI?start=3455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=1110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=1450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=1635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=1900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=1925&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2370&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=2925&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=3020&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=3055&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pZINGjQ86Hc?start=3580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=330&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1365&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1425&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1525&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=2055&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=2100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=2965&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=3270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/MfDdmsW3OMo?start=3870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1733&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1909&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=1950&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=2065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=2195&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=2885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=3152&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/EC0SVkFB2OU?start=3420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=950&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=1100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=1230&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=1345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=1565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=2035&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=2065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=2115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=2515&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=2955&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-W-OopvhNPo?start=3520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=415&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=1040&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=1085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=1615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=1745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=1780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=2125&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=2900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=3060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=3320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=3440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/2L-jA-Me3zg?start=3540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=240&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=1500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=1635&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=2115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=2235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=2585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/7G7SVODhVo4?start=3600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=1115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=1325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=1390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=1805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=2070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=2360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=2700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=2760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=2845&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=3165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=3275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/NY0-IFet5AM?start=3600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=755&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1475&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1640&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=1775&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=2260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=2420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=2465&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=2665&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-1x8Kpyndss?start=3035&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=80&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=555&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=783&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=850&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1170&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1545&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1633&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1735&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1775&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=1787&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=2245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=2350&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=2565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=3345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/E2amEz_upzU?start=3695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=677&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=921&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=1070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=1105&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=1200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=2375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=2605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=3185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=3940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=4245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/ImpXawPNCfM?start=4780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=110&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=610&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=630&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=1085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=1210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=1470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=1760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=2000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=2445&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=2700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=2820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=2900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=3160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/Rcmu5e-9FSc?start=3600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=1145&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=1615&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=1700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=2730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=2975&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=3000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=3060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/f7Rc1bvMgZY?start=3470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=920&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=1915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=2075&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=2140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=2210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/6V0vAx2Km7U?start=4645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=215&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=505&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=580&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=2000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=2210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=2700&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=2760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=2870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=3025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/0uqAhIiK9Rc?start=3410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=727&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=945&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=1235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=1295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=1605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=2520&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=3255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/bgcBEBqVnx8?start=3625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=1415&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=1645&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=2225&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=3050&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=3262&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=3460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=3722&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dHRPrVsnNwo?start=3900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=1020&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=1280&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=1595&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=2830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=3045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=3390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=3585&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/WT7FMn-_jPY?start=3810&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=490&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=915&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1065&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=1710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=2080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=2320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=2470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=2680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=3045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=3185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=3255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/vYbDyfv_v4Q?start=3715&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=1235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=1255&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=1300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=1935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=2085&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=2390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=2530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=2575&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=2825&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=3260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=3395&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/-RD8GNCNsCk?start=3590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=500&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=685&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=745&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=805&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=870&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=900&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1285&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1780&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=1985&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2015&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2200&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2375&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2505&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2680&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=2835&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=3025&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=3180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/BV_afpCDQ70?start=3300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=270&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=360&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=665&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1160&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1460&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1530&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1605&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1790&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=1965&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=2660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=2880&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=3180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=3380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/lY0YLDZhT88?start=3470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=450&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=570&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=840&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1070&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1235&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1770&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=1860&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2120&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2392&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=2545&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=3000&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pJPqAIb8MKA?start=3600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=85&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=150&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=220&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=310&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=1590&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=1720&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=1815&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/b1oKh9eeqkY?start=2325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=400&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=545&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=640&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=965&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=1100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=1390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=1830&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=2260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=2730&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=3022&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/4AhXvMsCooM?start=3565&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=345&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=355&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=390&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=405&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=420&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=510&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=800&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=905&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=1690&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=2045&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=2140&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=2305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=2320&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=2820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=3185&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=3485&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/pxJ5wtxL5Kw?start=3650&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=285&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=820&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=1155&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=1455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=1895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=1980&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=2440&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=2935&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=3480&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/8jNQzce13SE?start=3625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=290&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=470&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=625&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=835&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=860&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=995&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=1115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=1295&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=1760&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=2305&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=2495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=2655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=2765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=2905&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=3060&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=3380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/AqwA5EJfLXo?start=3550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=135&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=275&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=300&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=315&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=325&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=410&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=455&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=540&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=550&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=620&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=675&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=710&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=885&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=913&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=930&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1015&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1080&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1655&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=1695&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=2100&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=2180&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=2245&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=2600&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=3115&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/dM_0zjj4TtM?start=3560&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=210&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=260&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=355&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=380&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=750&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=895&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=970&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1030&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1090&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1130&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1215&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1285&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1495&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1535&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=1765&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2165&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2265&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2330&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2435&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2660&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2940&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=2960&autoplay=1\"},\"children\":[]}]},{\"name\":\"div\",\"attribs\":{\"style\":{\"text-align\":\"center\",\"padding\":\"10px\",\"background\":\"grey\"}},\"children\":[{\"name\":\"iframe\",\"attribs\":{\"height\":\"640\",\"width\":\"640\",\"allow\":\"fullscreen\",\"src\":\"https://www.youtube.com/embed/TSG74voJQ3E?start=3480&autoplay=1\"},\"children\":[]}]}]},{\"accessor\":\"Screencast\",\"name\":\"Screencast\",\"type\":\"character\"},{\"accessor\":\"Date\",\"name\":\"Date\",\"type\":\"Date\"},{\"accessor\":\"Timestamp\",\"name\":\"Timestamp\",\"type\":\"numeric\",\"show\":false},{\"accessor\":\"Link\",\"name\":\"Link\",\"type\":\"character\",\"show\":false},{\"accessor\":\"Description\",\"name\":\"Description\",\"type\":\"character\",\"width\":500},{\"accessor\":\"Functions\",\"name\":\"Functions\",\"type\":\"character\"}],\"searchable\":true,\"defaultPageSize\":10,\"paginationType\":\"numbers\",\"showPageInfo\":true,\"minRows\":1,\"bordered\":true,\"theme\":{\"style\":{\"fontSize\":\"14px\"},\"searchInputStyle\":{\"width\":\"100%\"}},\"dataKey\":\"40afa88b5ed9b526e2e716f8dd677234\",\"key\":\"40afa88b5ed9b526e2e716f8dd677234\"},\"children\":[]},\"class\":\"reactR_markup\"},\"evals\":[],\"jsHooks\":[]}\r\nCode\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(htmltools)\r\nlibrary(reactable)\r\n\r\n# David Robinson's (@drob) #tidytuesday screencast annotations, made by Alex Cookson (@alexcookson)\r\nscreencasts <-\r\n gsheet::gsheet2tbl(\"docs.google.com/spreadsheets/d/1pjj_G9ncJZPGTYPkR1BYwzA6bhJoeTfY2fJeGKSbOKM\") %>% \r\n select(Screencast, Date, Timestamp = `Timestamp (sec)`, Link:Functions) %>% \r\n mutate(Link = str_extract(Link, \"(?<=v=).*(?=&)\"))\r\n\r\n\r\n###############\r\n## The Table ##\r\n###############\r\n\r\nreactable(screencasts,\r\n \r\n # Function to embed Youtube Video \r\n details = function(index){\r\n \r\n # Grab video info from hidden columns\r\n link <- screencasts$Link[index]\r\n time <- screencasts$Timestamp[index]\r\n \r\n # Div container to add grey padding around the video\r\n tags$div(style = \"text-align:center; padding:10px; background:grey\",\r\n \r\n # The actual video\r\n tags$iframe(\r\n height = \"640\", width = \"640\", allow = \"fullscreen\",\r\n src = glue::glue(\"https://www.youtube.com/embed/{link}?start={time}&autoplay=1\")\r\n )\r\n \r\n )\r\n \r\n },\r\n \r\n # Column options\r\n columns = list(\r\n Link = colDef(show = F),\r\n Timestamp = colDef(show = F),\r\n Description = colDef(width = 500)\r\n ),\r\n \r\n # Some theme options\r\n searchable = TRUE,\r\n bordered = TRUE,\r\n fullWidth = TRUE,\r\n theme = reactableTheme(\r\n style = list(fontSize = '14px'),\r\n searchInputStyle = list(width = \"100%\")\r\n ),\r\n \r\n)\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-09-12-videos-in-reactable/preview.png", + "last_modified": "2021-06-11T03:40:10-04:00", + "input_file": {}, + "preview_width": 808, + "preview_height": 617 + }, + { + "path": "posts/2020-09-06-fonts-for-graphs/", + "title": "Fonts for graphs", + "description": "A small collection of my favorite fonts for data visualization", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-09-06", + "categories": [ + "data visualization", + "typography" + ], + "contents": "\r\n\r\n\r\n\r\n \r\nFor the last few weeks I’ve been reading about and experimenting with fonts for data visualization in my spare time.1 Out of that, I have found a couple fonts that I really like and wanted to do a small showcase of them here.\r\nThese fonts are all free and available for download at Google Fonts.2 Note that not only are they all large font families that come with many different styles, you can also adjust various theme settings like lineheight in {ggplot2}, so what I’m showing here isn’t the full extent of what you can make with these fonts.\r\n \r\n\r\nArial\r\nIt’s the default. It’s dull. It’s just here for comparison.\r\n\r\nMontserrat\r\nSimple design that can handle long lines of text. I like it for minimal plots.\r\n\r\nRoboto Mono\r\nMonospaced member of the Roboto family. Very easy to read.\r\n\r\nFutura Bk BT\r\nA slender and bold member of the Futura family. Looks nice even in larger sizes.\r\n\r\nBarlow\r\nAlso a slender font like Futura, but this has nicer ’j’s\r\n\r\nAdelle\r\nA serif font that doesn’t go overboard. I use it a lot for short paragraphs.\r\n\r\nMerriweather\r\nSimilar to Adelle, but has a bit more pronounced hooks\r\n\r\n\r\n \r\nMisc.\r\nWhy spend 3 minutes copy-pasting code when you can spend an hour automatizing it?\r\nThis was my first time using dynamic Rmarkdown reporting. The plots above and the text descriptions that went with them were generated in a for loop, which I learned about here.\r\nHere is the single chunk of code that made this possible:\r\n\r\n\r\nlibrary(ggplot2)\r\nlibrary(extrafont)\r\nknitr::opts_chunk$set(fig.width = 7, dpi = 600)\r\n\r\ntheme_set(theme_classic(base_size = 14))\r\n\r\nfavorites <- c(\r\n \"Arial\" = \"It's the default. It's dull. It's just here for comparison.\",\r\n \"Montserrat\" = \"Simple design that can handle long lines of text. I like it for minimal plots.\",\r\n \"Roboto Mono\" = \"Monospaced member of the Roboto family. Very easy to read.\",\r\n \"Futura Bk BT\" = \"A slender and bold member of the Futura family. Looks nice even in larger sizes.\",\r\n \"Barlow\" = \"Also a slender font like Futura, but this has nicer 'j's\",\r\n \"Adelle\" = \"A serif font that doesn't go overboard. I use it a lot for short paragraphs.\",\r\n \"Merriweather\" = \"Similar to Adelle, but has a bit more pronounced hooks\"\r\n)\r\n\r\n\r\nfor (font in names(favorites)) {\r\n cat(\"\\n\\n## \", font, \"\\n\\n\")\r\n cat(\"\", favorites[font], \"\\n\\n\")\r\n plot <- qplot(data = mtcars, mpg, disp, color = factor(cyl)) +\r\n annotate(\"text\", 28, 400, label = paste(letters, collapse = ''), family = font) +\r\n geom_curve(aes(x = 28, y = 380, xend = 22, yend = 260),\r\n color = 'black', curvature = -.3, arrow = arrow(), show.legend = FALSE) +\r\n labs(title = \"This is an interesting plot title\",\r\n subtitle = \"Here's the subtitle 1234567890\",\r\n caption = \"This is the plot caption\") +\r\n theme(text = element_text(family = font),\r\n plot.title.position = 'plot')\r\n print(plot)\r\n}\r\n\r\n\r\n\r\n\r\nI reference a lot this great collection of fonts used in profesional visualization here.↩︎\r\nFor how to import local fonts into R to use for plotting, check out {extrafont} and/or {showtext}.↩︎\r\n", + "preview": "posts/2020-09-06-fonts-for-graphs/preview.png", + "last_modified": "2020-11-01T19:42:42-05:00", + "input_file": {}, + "preview_width": 1144, + "preview_height": 675 + }, + { + "path": "posts/2020-08-17-tidytuesday-2020-week-33/", + "title": "TidyTuesday 2020 Week 33", + "description": "An animation of the main characters in Avatar", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-08-17", + "categories": [ + "tidytuesday", + "gganimate", + "ggplot2" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n \r\n\r\n\r\n\r\nThings I learned\r\nReally basic image manipulation with {magick}\r\nThat you can get away with not doing the data part of data visualization for TidyTuesday\r\nThings to improve\r\nShould’ve picked a better color to represent air for Aang.\r\nNot sure why it looks like white grid lines are there. All my attempts at getting rid of them failed, so I’ve just concluded that they’re likely an optical illusion.\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(magick)\r\nlibrary(gganimate)\r\n\r\naang <- image_read(\"https://vignette.wikia.nocookie.net/avatar/images/a/ae/Aang_at_Jasmine_Dragon.png\")\r\niroh <- image_read(\"https://vignette.wikia.nocookie.net/avatar/images/c/c1/Iroh_smiling.png\")\r\nsokka <- image_read(\"https://vignette.wikia.nocookie.net/avatar/images/c/cc/Sokka.png\")\r\ntoph <- image_read(\"https://vignette.wikia.nocookie.net/avatar/images/4/46/Toph_Beifong.png\")\r\n\r\n# Script by Georgios Karamanis adapted and wrapped into a function\r\n# - from https://github.com/gkaramanis/aRt/blob/master/split-bar/points-portraits.R\r\nimg_to_df <- function(img, index) {\r\n \r\n img <- image_convert(img, colorspace = \"gray\")\r\n \r\n img_w <- image_info(img)$width\r\n img_h <- image_info(img)$height\r\n \r\n if (img_w >= img_h) {\r\n img <- image_resize(img, \"120\")\r\n } else {\r\n img <- image_resize(img, (\"x120\"))\r\n }\r\n \r\n img_array <- drop(as.integer(img[[1]]))\r\n rownames(img_array) <- 1:nrow(img_array)\r\n colnames(img_array) <- 1:ncol(img_array)\r\n \r\n as.data.frame.table(img_array) %>% \r\n `colnames<-`(c(\"y\", \"x\", \"b\")) %>% \r\n mutate(\r\n across(everything(), as.numeric),\r\n bf = 1 - b / 255\r\n ) %>% \r\n mutate(character_id = index)\r\n}\r\n\r\nplot_data <- imap_dfr(list(aang, iroh, sokka, toph), ~img_to_df(.x, .y)) %>% \r\n group_by(character_id) %>% \r\n mutate(point_id = 1:n()) %>% \r\n ungroup() %>% \r\n mutate(across(contains(\"id\"), as.factor))\r\n\r\nanim <- ggplot(plot_data) +\r\n geom_point(aes(x = x, y = y, size = bf, group = point_id, color = character_id),\r\n shape = 16, show.legend = FALSE) +\r\n scale_y_reverse() +\r\n scale_size_continuous(range = c(0, 4)) +\r\n scale_color_manual(values = c(\"#C0EDFF\", \"#B33000\", \"#206BA4\", \"#8B4513\")) +\r\n coord_fixed(expand = FALSE) +\r\n theme_void() +\r\n theme(panel.grid = element_blank()) +\r\n transition_states(id)\r\n\r\nanimate(anim, width = 12, height = 9, units = \"in\", res = 120)\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-08-17-tidytuesday-2020-week-33/preview.png", + "last_modified": "2020-11-01T19:44:08-05:00", + "input_file": {}, + "preview_width": 1289, + "preview_height": 964 + }, + { + "path": "posts/2020-08-07-saving-a-line-of-piping/", + "title": "Saving a line of piping", + "description": "Some notes on lesser known functions/functionalities that combine common chain of {dplyr} verbs.", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-08-07", + "categories": [ + "data wrangling", + "dplyr", + "tutorial" + ], + "contents": "\r\n\r\nContents\r\n1. rename() inside select()\r\n2. rename() inside count()\r\n3. mutate() inside count()\r\n4. transmute() + select()\r\n5. ungroup() inside summarize()\r\n6. arrange() + other features inside slice()\r\n7. count and sum by group with add_count()\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nUsing a cleaned up version of penguins data from {palmerpenguins}:\r\n\r\n\r\ndata(\"penguins\", package = \"palmerpenguins\")\r\n\r\npenguins <- na.omit(penguins)\r\n\r\n\r\n\r\n\r\n\r\n{\"x\":{\"tag\":{\"name\":\"Reactable\",\"attribs\":{\"data\":{\"species\":[\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Adelie\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Gentoo\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\",\"Chinstrap\"],\"island\":[\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Torgersen\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Biscoe\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\",\"Dream\"],\"bill_length_mm\":[39.1,39.5,40.3,36.7,39.3,38.9,39.2,41.1,38.6,34.6,36.6,38.7,42.5,34.4,46,37.8,37.7,35.9,38.2,38.8,35.3,40.6,40.5,37.9,40.5,39.5,37.2,39.5,40.9,36.4,39.2,38.8,42.2,37.6,39.8,36.5,40.8,36,44.1,37,39.6,41.1,36,42.3,39.6,40.1,35,42,34.5,41.4,39,40.6,36.5,37.6,35.7,41.3,37.6,41.1,36.4,41.6,35.5,41.1,35.9,41.8,33.5,39.7,39.6,45.8,35.5,42.8,40.9,37.2,36.2,42.1,34.6,42.9,36.7,35.1,37.3,41.3,36.3,36.9,38.3,38.9,35.7,41.1,34,39.6,36.2,40.8,38.1,40.3,33.1,43.2,35,41,37.7,37.8,37.9,39.7,38.6,38.2,38.1,43.2,38.1,45.6,39.7,42.2,39.6,42.7,38.6,37.3,35.7,41.1,36.2,37.7,40.2,41.4,35.2,40.6,38.8,41.5,39,44.1,38.5,43.1,36.8,37.5,38.1,41.1,35.6,40.2,37,39.7,40.2,40.6,32.1,40.7,37.3,39,39.2,36.6,36,37.8,36,41.5,46.1,50,48.7,50,47.6,46.5,45.4,46.7,43.3,46.8,40.9,49,45.5,48.4,45.8,49.3,42,49.2,46.2,48.7,50.2,45.1,46.5,46.3,42.9,46.1,47.8,48.2,50,47.3,42.8,45.1,59.6,49.1,48.4,42.6,44.4,44,48.7,42.7,49.6,45.3,49.6,50.5,43.6,45.5,50.5,44.9,45.2,46.6,48.5,45.1,50.1,46.5,45,43.8,45.5,43.2,50.4,45.3,46.2,45.7,54.3,45.8,49.8,49.5,43.5,50.7,47.7,46.4,48.2,46.5,46.4,48.6,47.5,51.1,45.2,45.2,49.1,52.5,47.4,50,44.9,50.8,43.4,51.3,47.5,52.1,47.5,52.2,45.5,49.5,44.5,50.8,49.4,46.9,48.4,51.1,48.5,55.9,47.2,49.1,46.8,41.7,53.4,43.3,48.1,50.5,49.8,43.5,51.5,46.2,55.1,48.8,47.2,46.8,50.4,45.2,49.9,46.5,50,51.3,45.4,52.7,45.2,46.1,51.3,46,51.3,46.6,51.7,47,52,45.9,50.5,50.3,58,46.4,49.2,42.4,48.5,43.2,50.6,46.7,52,50.5,49.5,46.4,52.8,40.9,54.2,42.5,51,49.7,47.5,47.6,52,46.9,53.5,49,46.2,50.9,45.5,50.9,50.8,50.1,49,51.5,49.8,48.1,51.4,45.7,50.7,42.5,52.2,45.2,49.3,50.2,45.6,51.9,46.8,45.7,55.8,43.5,49.6,50.8,50.2],\"bill_depth_mm\":[18.7,17.4,18,19.3,20.6,17.8,19.6,17.6,21.2,21.1,17.8,19,20.7,18.4,21.5,18.3,18.7,19.2,18.1,17.2,18.9,18.6,17.9,18.6,18.9,16.7,18.1,17.8,18.9,17,21.1,20,18.5,19.3,19.1,18,18.4,18.5,19.7,16.9,18.8,19,17.9,21.2,17.7,18.9,17.9,19.5,18.1,18.6,17.5,18.8,16.6,19.1,16.9,21.1,17,18.2,17.1,18,16.2,19.1,16.6,19.4,19,18.4,17.2,18.9,17.5,18.5,16.8,19.4,16.1,19.1,17.2,17.6,18.8,19.4,17.8,20.3,19.5,18.6,19.2,18.8,18,18.1,17.1,18.1,17.3,18.9,18.6,18.5,16.1,18.5,17.9,20,16,20,18.6,18.9,17.2,20,17,19,16.5,20.3,17.7,19.5,20.7,18.3,17,20.5,17,18.6,17.2,19.8,17,18.5,15.9,19,17.6,18.3,17.1,18,17.9,19.2,18.5,18.5,17.6,17.5,17.5,20.1,16.5,17.9,17.1,17.2,15.5,17,16.8,18.7,18.6,18.4,17.8,18.1,17.1,18.5,13.2,16.3,14.1,15.2,14.5,13.5,14.6,15.3,13.4,15.4,13.7,16.1,13.7,14.6,14.6,15.7,13.5,15.2,14.5,15.1,14.3,14.5,14.5,15.8,13.1,15.1,15,14.3,15.3,15.3,14.2,14.5,17,14.8,16.3,13.7,17.3,13.6,15.7,13.7,16,13.7,15,15.9,13.9,13.9,15.9,13.3,15.8,14.2,14.1,14.4,15,14.4,15.4,13.9,15,14.5,15.3,13.8,14.9,13.9,15.7,14.2,16.8,16.2,14.2,15,15,15.6,15.6,14.8,15,16,14.2,16.3,13.8,16.4,14.5,15.6,14.6,15.9,13.8,17.3,14.4,14.2,14,17,15,17.1,14.5,16.1,14.7,15.7,15.8,14.6,14.4,16.5,15,17,15.5,15,16.1,14.7,15.8,14,15.1,15.2,15.9,15.2,16.3,14.1,16,16.2,13.7,14.3,15.7,14.8,16.1,17.9,19.5,19.2,18.7,19.8,17.8,18.2,18.2,18.9,19.9,17.8,20.3,17.3,18.1,17.1,19.6,20,17.8,18.6,18.2,17.3,17.5,16.6,19.4,17.9,19,18.4,19,17.8,20,16.6,20.8,16.7,18.8,18.6,16.8,18.3,20.7,16.6,19.9,19.5,17.5,19.1,17,17.9,18.5,17.9,19.6,18.7,17.3,16.4,19,17.3,19.7,17.3,18.8,16.6,19.9,18.8,19.4,19.5,16.5,17,19.8,18.1,18.2,19,18.7],\"flipper_length_mm\":[181,186,195,193,190,181,195,182,191,198,185,195,197,184,194,174,180,189,185,180,187,183,187,172,180,178,178,188,184,195,196,190,180,181,184,182,195,186,196,185,190,182,190,191,186,188,190,200,187,191,186,193,181,194,185,195,185,192,184,192,195,188,190,198,190,190,196,197,190,195,191,184,187,195,189,196,187,193,191,194,190,189,189,190,202,205,185,186,187,208,190,196,178,192,192,203,183,190,193,184,199,190,181,197,198,191,193,197,191,196,188,199,189,189,187,198,176,202,186,199,191,195,191,210,190,197,193,199,187,190,191,200,185,193,193,187,188,190,192,185,190,184,195,193,187,201,211,230,210,218,215,210,211,219,209,215,214,216,214,213,210,217,210,221,209,222,218,215,213,215,215,215,215,210,220,222,209,207,230,220,220,213,219,208,208,208,225,210,216,222,217,210,225,213,215,210,220,210,225,217,220,208,220,208,224,208,221,214,231,219,230,229,220,223,216,221,221,217,216,230,209,220,215,223,212,221,212,224,212,228,218,218,212,230,218,228,212,224,214,226,216,222,203,225,219,228,215,228,215,210,219,208,209,216,229,213,230,217,230,222,214,215,222,212,213,192,196,193,188,197,198,178,197,195,198,193,194,185,201,190,201,197,181,190,195,181,191,187,193,195,197,200,200,191,205,187,201,187,203,195,199,195,210,192,205,210,187,196,196,196,201,190,212,187,198,199,201,193,203,187,197,191,203,202,194,206,189,195,207,202,193,210,198],\"body_mass_g\":[3750,3800,3250,3450,3650,3625,4675,3200,3800,4400,3700,3450,4500,3325,4200,3400,3600,3800,3950,3800,3800,3550,3200,3150,3950,3250,3900,3300,3900,3325,4150,3950,3550,3300,4650,3150,3900,3100,4400,3000,4600,3425,3450,4150,3500,4300,3450,4050,2900,3700,3550,3800,2850,3750,3150,4400,3600,4050,2850,3950,3350,4100,3050,4450,3600,3900,3550,4150,3700,4250,3700,3900,3550,4000,3200,4700,3800,4200,3350,3550,3800,3500,3950,3600,3550,4300,3400,4450,3300,4300,3700,4350,2900,4100,3725,4725,3075,4250,2925,3550,3750,3900,3175,4775,3825,4600,3200,4275,3900,4075,2900,3775,3350,3325,3150,3500,3450,3875,3050,4000,3275,4300,3050,4000,3325,3500,3500,4475,3425,3900,3175,3975,3400,4250,3400,3475,3050,3725,3000,3650,4250,3475,3450,3750,3700,4000,4500,5700,4450,5700,5400,4550,4800,5200,4400,5150,4650,5550,4650,5850,4200,5850,4150,6300,4800,5350,5700,5000,4400,5050,5000,5100,5650,4600,5550,5250,4700,5050,6050,5150,5400,4950,5250,4350,5350,3950,5700,4300,4750,5550,4900,4200,5400,5100,5300,4850,5300,4400,5000,4900,5050,4300,5000,4450,5550,4200,5300,4400,5650,4700,5700,5800,4700,5550,4750,5000,5100,5200,4700,5800,4600,6000,4750,5950,4625,5450,4725,5350,4750,5600,4600,5300,4875,5550,4950,5400,4750,5650,4850,5200,4925,4875,4625,5250,4850,5600,4975,5500,5500,4700,5500,4575,5500,5000,5950,4650,5500,4375,5850,6000,4925,4850,5750,5200,5400,3500,3900,3650,3525,3725,3950,3250,3750,4150,3700,3800,3775,3700,4050,3575,4050,3300,3700,3450,4400,3600,3400,2900,3800,3300,4150,3400,3800,3700,4550,3200,4300,3350,4100,3600,3900,3850,4800,2700,4500,3950,3650,3550,3500,3675,4450,3400,4300,3250,3675,3325,3950,3600,4050,3350,3450,3250,4050,3800,3525,3950,3650,3650,4000,3400,3775,4100,3775],\"sex\":[\"male\",\"female\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\",\"male\",\"female\",\"female\",\"male\",\"female\",\"male\",\"male\",\"female\"],\"year\":[2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009]},\"columns\":[{\"accessor\":\"species\",\"name\":\"species\",\"type\":\"factor\"},{\"accessor\":\"island\",\"name\":\"island\",\"type\":\"factor\"},{\"accessor\":\"bill_length_mm\",\"name\":\"bill_length_mm\",\"type\":\"numeric\"},{\"accessor\":\"bill_depth_mm\",\"name\":\"bill_depth_mm\",\"type\":\"numeric\"},{\"accessor\":\"flipper_length_mm\",\"name\":\"flipper_length_mm\",\"type\":\"numeric\"},{\"accessor\":\"body_mass_g\",\"name\":\"body_mass_g\",\"type\":\"numeric\"},{\"accessor\":\"sex\",\"name\":\"sex\",\"type\":\"factor\"},{\"accessor\":\"year\",\"name\":\"year\",\"type\":\"numeric\"}],\"sortable\":false,\"defaultPageSize\":5,\"paginationType\":\"numbers\",\"showPageInfo\":true,\"minRows\":1,\"bordered\":true,\"nowrap\":true,\"dataKey\":\"b650b7a1a5c792f49c2b2303a0449c36\",\"key\":\"b650b7a1a5c792f49c2b2303a0449c36\"},\"children\":[]},\"class\":\"reactR_markup\"},\"evals\":[],\"jsHooks\":[]}\r\n1. rename() inside select()\r\nYou can rename a column inside select() by assigning a new name on the left hand side:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# select(species, island) %>% \r\n# rename(penguin_species = species)\r\n\r\npenguins %>% \r\n select(penguin_species = species,\r\n island)\r\n\r\n\r\n # A tibble: 333 x 2\r\n penguin_species island \r\n \r\n 1 Adelie Torgersen\r\n 2 Adelie Torgersen\r\n 3 Adelie Torgersen\r\n 4 Adelie Torgersen\r\n 5 Adelie Torgersen\r\n 6 Adelie Torgersen\r\n 7 Adelie Torgersen\r\n 8 Adelie Torgersen\r\n 9 Adelie Torgersen\r\n 10 Adelie Torgersen\r\n # ... with 323 more rows\r\n\r\nThis also works with {tidyselect} helpers like starts_with(), ends_with(), contains(), and matches():\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# select(species, island) %>% \r\n# rename(penguin_species = species,\r\n# weight = body_weight_g)\r\n\r\npenguins %>% \r\n select(penguin_species = species,\r\n island,\r\n weight = contains(\"mass\"))\r\n\r\n\r\n # A tibble: 333 x 3\r\n penguin_species island weight\r\n \r\n 1 Adelie Torgersen 3750\r\n 2 Adelie Torgersen 3800\r\n 3 Adelie Torgersen 3250\r\n 4 Adelie Torgersen 3450\r\n 5 Adelie Torgersen 3650\r\n 6 Adelie Torgersen 3625\r\n 7 Adelie Torgersen 4675\r\n 8 Adelie Torgersen 3200\r\n 9 Adelie Torgersen 3800\r\n 10 Adelie Torgersen 4400\r\n # ... with 323 more rows\r\n\r\n2. rename() inside count()\r\nYou can rename the new column of counts (n by default) using the name argument:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# count(species) %>% \r\n# rename(total = n)\r\n\r\npenguins %>% \r\n count(species, name = \"total\")\r\n\r\n\r\n # A tibble: 3 x 2\r\n species total\r\n \r\n 1 Adelie 146\r\n 2 Chinstrap 68\r\n 3 Gentoo 119\r\n\r\nYou can also rename the column(s) that are selected for counting in the same way as shown in the select() examples above:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# count(species) %>% \r\n# rename(total = n,\r\n# penguin_species = species)\r\n\r\npenguins %>% \r\n count(penguin_species = species, name = \"total\")\r\n\r\n\r\n # A tibble: 3 x 2\r\n penguin_species total\r\n \r\n 1 Adelie 146\r\n 2 Chinstrap 68\r\n 3 Gentoo 119\r\n\r\nNote that the new name passed into the name argument must be quoted, but the new name for selected column needs not to be unquoted:\r\n\r\n\r\nidentical(\r\n # Method 1: new column name UNQUOTED\r\n penguins %>% \r\n count(penguin_species = species, name = \"total\"),\r\n # Method 2: new column name QUOTED\r\n penguins %>% \r\n count(\"penguin_species\" = species, name = \"total\") \r\n)\r\n\r\n\r\n [1] TRUE\r\n\r\nI prefer to unquote the new column names to keep it consistent with the recommended style for rename()\r\nThis feature of select() may seem weird and hackish (and I guess it sort of is in this demonstration) but it’s explicitly documented here if you want to read more on it.\r\n3. mutate() inside count()\r\nYou can also create a new column to count by inside count(). This works very similarly to the above, but I think it’s worth its own mention.\r\nIt’s pretty simple - you just do what you’d do for mutate() inside count():\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# mutate(long_beak = bill_length_mm > 50) %>% \r\n# count(long_beak)\r\n\r\npenguins %>% \r\n count(long_beak = bill_length_mm > 50)\r\n\r\n\r\n # A tibble: 2 x 2\r\n long_beak n\r\n \r\n 1 FALSE 281\r\n 2 TRUE 52\r\n\r\nAnd of course, this also works when specifying multiple variables to count by:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# mutate(long_beak = bill_length_mm > 50,\r\n# is_adelie = species == \"Adelie\") %>% \r\n# count(is_adelie, long_beak)\r\n\r\npenguins %>% \r\n count(long_beak = bill_length_mm > 50,\r\n is_adelie = species == \"Adelie\")\r\n\r\n\r\n # A tibble: 3 x 3\r\n long_beak is_adelie n\r\n \r\n 1 FALSE FALSE 135\r\n 2 FALSE TRUE 146\r\n 3 TRUE FALSE 52\r\n\r\n4. transmute() + select()\r\ntransmute() is a function that mutates columns and returns only those columns:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# mutate(body_mass_kg = body_mass_g/1000) %>% \r\n# select(body_mass_kg)\r\n\r\npenguins %>% \r\n transmute(body_mass_kg = body_mass_g/1000)\r\n\r\n\r\n # A tibble: 333 x 1\r\n body_mass_kg\r\n \r\n 1 3.75\r\n 2 3.8 \r\n 3 3.25\r\n 4 3.45\r\n 5 3.65\r\n 6 3.62\r\n 7 4.68\r\n 8 3.2 \r\n 9 3.8 \r\n 10 4.4 \r\n # ... with 323 more rows\r\n\r\nI’ve rarely used transmute() in the past because I thought it could only return modified columns, which would be very limiting (like in the above example, what good is a single column of penguin body mass in kilograms?)\r\nBut actually you can just name the columns you want to include in transmute() like you would in select() to carry over columns that you aren’t modifying. And of course, you can “rename” them as you do it1:\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# mutate(body_mass_kg = body_mass_g/1000) %>% \r\n# select(species, island, body_mass_kg) %>% \r\n# rename(penguin_species = species)\r\n\r\npenguins %>% \r\n transmute(penguin_species = species,\r\n island,\r\n body_mass_kg = body_mass_g/1000)\r\n\r\n\r\n # A tibble: 333 x 3\r\n penguin_species island body_mass_kg\r\n \r\n 1 Adelie Torgersen 3.75\r\n 2 Adelie Torgersen 3.8 \r\n 3 Adelie Torgersen 3.25\r\n 4 Adelie Torgersen 3.45\r\n 5 Adelie Torgersen 3.65\r\n 6 Adelie Torgersen 3.62\r\n 7 Adelie Torgersen 4.68\r\n 8 Adelie Torgersen 3.2 \r\n 9 Adelie Torgersen 3.8 \r\n 10 Adelie Torgersen 4.4 \r\n # ... with 323 more rows\r\n\r\n5. ungroup() inside summarize()\r\nI always found using ungroup() after summarize() to be extremely ugly, but I found myself using it a lot to remove left-over groupings after a summarize call:\r\n\r\n\r\npenguins %>% \r\n group_by(island, species) %>% \r\n summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% \r\n ungroup()\r\n\r\n\r\n # A tibble: 5 x 3\r\n island species mean_mass\r\n \r\n 1 Biscoe Adelie 3710.\r\n 2 Biscoe Gentoo 5092.\r\n 3 Dream Adelie 3701.\r\n 4 Dream Chinstrap 3733.\r\n 5 Torgersen Adelie 3709.\r\n\r\n… because summarize() only drops the last grouping variable by defaut, meaning that the output is still grouped by the island variable if ungroup() isn’t called:\r\n\r\n\r\n# Without ungroup()\r\npenguins %>% \r\n group_by(island, species) %>% \r\n summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% \r\n group_vars()\r\n\r\n\r\n [1] \"island\"\r\n\r\n# With ungroup()\r\npenguins %>% \r\n group_by(island, species) %>% \r\n summarize(mean_mass = mean(body_mass_g, na.rm = TRUE)) %>% \r\n ungroup() %>% \r\n group_vars()\r\n\r\n\r\n character(0)\r\n\r\nSince {dplyr} 1.0.0, you can simply set the .groups argument inside summarize() to 'drop' to achieve the same:\r\n\r\n\r\npenguins %>% \r\n group_by(island, species) %>% \r\n summarize(mean_mass = mean(body_mass_g, na.rm = TRUE), .groups = 'drop')\r\n\r\n\r\n # A tibble: 5 x 3\r\n island species mean_mass\r\n \r\n 1 Biscoe Adelie 3710.\r\n 2 Biscoe Gentoo 5092.\r\n 3 Dream Adelie 3701.\r\n 4 Dream Chinstrap 3733.\r\n 5 Torgersen Adelie 3709.\r\n\r\nBut ungroup() still remains relevant as you can now selectively remove grouping variables in {dplyr} 1.0.0.\r\n6. arrange() + other features inside slice()\r\nIn past versions of {dplyr}, if you wanted to grab the top n rows sorted by a column, you’d use top_n(), which provides a simpler way of doing slice() + arrange():\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# arrange(desc(body_mass_g)) %>% \r\n# slice(1:5)\r\n\r\npenguins %>% \r\n top_n(5, wt = body_mass_g)\r\n\r\n\r\n # A tibble: 6 x 8\r\n species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex \r\n \r\n 1 Gentoo Biscoe 49.2 15.2 221 6300 male \r\n 2 Gentoo Biscoe 59.6 17 230 6050 male \r\n 3 Gentoo Biscoe 51.1 16.3 220 6000 male \r\n 4 Gentoo Biscoe 45.2 16.4 223 5950 male \r\n 5 Gentoo Biscoe 49.8 15.9 229 5950 male \r\n 6 Gentoo Biscoe 48.8 16.2 222 6000 male \r\n # ... with 1 more variable: year \r\n\r\nBut the recent {dplyr} 1.0.0 augmented slice() with variants like slice_min() and slice_max() that now supresede top_n():\r\n\r\n\r\n##### Pre-1.0.0 #####\r\n# penguins %>% \r\n# top_n(5, wt = body_mass_g)\r\n\r\npenguins %>% \r\n slice_max(order_by = body_mass_g, n = 5)\r\n\r\n\r\n # A tibble: 6 x 8\r\n species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex \r\n \r\n 1 Gentoo Biscoe 49.2 15.2 221 6300 male \r\n 2 Gentoo Biscoe 59.6 17 230 6050 male \r\n 3 Gentoo Biscoe 51.1 16.3 220 6000 male \r\n 4 Gentoo Biscoe 48.8 16.2 222 6000 male \r\n 5 Gentoo Biscoe 45.2 16.4 223 5950 male \r\n 6 Gentoo Biscoe 49.8 15.9 229 5950 male \r\n # ... with 1 more variable: year \r\n\r\nNote that the order of arguments is different for slice_min/max() - the first argument after piping is where you specify the variable for ordering rather than the number of rows to return, like in top_n().\r\nThis is because slice_min/max() gives you an option to either specify a certain number of rows n or a proportion of rows prop:\r\n\r\n\r\npenguins %>% \r\n slice_max(body_mass_g, prop = .01)\r\n\r\n\r\n # A tibble: 4 x 8\r\n species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g sex \r\n \r\n 1 Gentoo Biscoe 49.2 15.2 221 6300 male \r\n 2 Gentoo Biscoe 59.6 17 230 6050 male \r\n 3 Gentoo Biscoe 51.1 16.3 220 6000 male \r\n 4 Gentoo Biscoe 48.8 16.2 222 6000 male \r\n # ... with 1 more variable: year \r\n\r\nAnd actually, the most significant change with the new slice_*() functions is from adding appropriate behavior for grouped dataframes.\r\nSo for example, this example below returns the top 5% of penguins by weight for each species:\r\n\r\n\r\npenguins %>% \r\n group_by(species) %>% \r\n slice_max(body_mass_g, prop = .05)\r\n\r\n\r\n # A tibble: 16 x 8\r\n # Groups: species [3]\r\n species island bill_length_mm bill_depth_mm flipper_length_~ body_mass_g\r\n \r\n 1 Adelie Biscoe 43.2 19 197 4775\r\n 2 Adelie Biscoe 41 20 203 4725\r\n 3 Adelie Torge~ 42.9 17.6 196 4700\r\n 4 Adelie Torge~ 39.2 19.6 195 4675\r\n 5 Adelie Dream 39.8 19.1 184 4650\r\n 6 Adelie Dream 39.6 18.8 190 4600\r\n 7 Adelie Biscoe 45.6 20.3 191 4600\r\n 8 Chinst~ Dream 52 20.7 210 4800\r\n 9 Chinst~ Dream 52.8 20 205 4550\r\n 10 Chinst~ Dream 53.5 19.9 205 4500\r\n 11 Gentoo Biscoe 49.2 15.2 221 6300\r\n 12 Gentoo Biscoe 59.6 17 230 6050\r\n 13 Gentoo Biscoe 51.1 16.3 220 6000\r\n 14 Gentoo Biscoe 48.8 16.2 222 6000\r\n 15 Gentoo Biscoe 45.2 16.4 223 5950\r\n 16 Gentoo Biscoe 49.8 15.9 229 5950\r\n # ... with 2 more variables: sex , year \r\n\r\nBut note that slice_*() functions do not modify groups in the result if the input is a grouped dataframe, so you need to explicitly add a call to ungroup() if you want to drop groups after slicing.\r\n7. count and sum by group with add_count()\r\nSaving my favorite lesser-known {dplyr} function for last!\r\nadd_count() adds a column with the counts of each group (or combination of groups):\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# group_by(species) %>% \r\n# mutate(count_by_species = n()) %>% \r\n# ungroup()\r\n\r\npenguins %>% \r\n add_count(species, name = \"count_by_species\") %>% \r\n # cutting down some columns to show the new column\r\n select(-contains(\"mm\"))\r\n\r\n\r\n # A tibble: 333 x 6\r\n species island body_mass_g sex year count_by_species\r\n \r\n 1 Adelie Torgersen 3750 male 2007 146\r\n 2 Adelie Torgersen 3800 female 2007 146\r\n 3 Adelie Torgersen 3250 female 2007 146\r\n 4 Adelie Torgersen 3450 female 2007 146\r\n 5 Adelie Torgersen 3650 male 2007 146\r\n 6 Adelie Torgersen 3625 female 2007 146\r\n 7 Adelie Torgersen 4675 male 2007 146\r\n 8 Adelie Torgersen 3200 female 2007 146\r\n 9 Adelie Torgersen 3800 male 2007 146\r\n 10 Adelie Torgersen 4400 male 2007 146\r\n # ... with 323 more rows\r\n\r\nYou can use the wt to effectively get sums by group (perhaps hackish but very very useful):\r\n\r\n\r\n##### Long Form #####\r\n# penguins %>% \r\n# group_by(species) %>% \r\n# mutate(total_weight_by_species = sum(body_mass_g)) %>% \r\n# ungroup()\r\n \r\n\r\npenguins %>% \r\n add_count(species, wt = body_mass_g, name = \"total_weight_by_species\") %>% \r\n # cutting down some columns to show the new column\r\n select(-contains(\"mm\"))\r\n\r\n\r\n # A tibble: 333 x 6\r\n species island body_mass_g sex year total_weight_by_species\r\n \r\n 1 Adelie Torgersen 3750 male 2007 541100\r\n 2 Adelie Torgersen 3800 female 2007 541100\r\n 3 Adelie Torgersen 3250 female 2007 541100\r\n 4 Adelie Torgersen 3450 female 2007 541100\r\n 5 Adelie Torgersen 3650 male 2007 541100\r\n 6 Adelie Torgersen 3625 female 2007 541100\r\n 7 Adelie Torgersen 4675 male 2007 541100\r\n 8 Adelie Torgersen 3200 female 2007 541100\r\n 9 Adelie Torgersen 3800 male 2007 541100\r\n 10 Adelie Torgersen 4400 male 2007 541100\r\n # ... with 323 more rows\r\n\r\nAlso check out its more primitive version add_tally().\r\nBy default, add_tally() adds a count of rows, which you can already do with mutate(n = n()), but it shines when you make use of its wt argument:\r\n\r\n\r\npenguins %>% \r\n add_count(species, wt = body_mass_g, name = \"total_weight_by_species\") %>% \r\n add_tally(wt = body_mass_g, name = \"total_weight_of_all_species\") %>% \r\n select(1:2, last_col(0):last_col(1))\r\n\r\n\r\n # A tibble: 333 x 4\r\n species island total_weight_of_all_species total_weight_by_species\r\n \r\n 1 Adelie Torgersen 1400950 541100\r\n 2 Adelie Torgersen 1400950 541100\r\n 3 Adelie Torgersen 1400950 541100\r\n 4 Adelie Torgersen 1400950 541100\r\n 5 Adelie Torgersen 1400950 541100\r\n 6 Adelie Torgersen 1400950 541100\r\n 7 Adelie Torgersen 1400950 541100\r\n 8 Adelie Torgersen 1400950 541100\r\n 9 Adelie Torgersen 1400950 541100\r\n 10 Adelie Torgersen 1400950 541100\r\n # ... with 323 more rows\r\n\r\n\r\nWhat happens under the hood is actually copying of a sort, so this is probably not the best approach if you care about efficiency. As a case in point, you can’t use {tidyselect} helpers in transmute because you’re creating a new dataframe↩︎\r\n", + "preview": "posts/2020-08-07-saving-a-line-of-piping/preview.png", + "last_modified": "2020-11-04T22:34:55-05:00", + "input_file": {}, + "preview_width": 877, + "preview_height": 372 + }, + { + "path": "posts/2020-08-04-tidytuesday-2020-week-32/", + "title": "TidyTuesday 2020 Week 32", + "description": "A dumbbell chart visualization of energy production trends among European countries", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-08-04", + "categories": [ + "tidytuesday", + "data visualization", + "ggplot2" + ], + "contents": "\r\n\r\nContents\r\nVisualization\r\nThings I learned\r\nThings to improve\r\n\r\nCode\r\n\r\n\r\n\r\n\r\nVisualization\r\n \r\n\r\n\r\n\r\nThings I learned\r\ngeom_dumbbell() from {ggalt}\r\ncoord_capped_cart() and facet_rep_wrap() from {lemon}\r\nUsing the reorder_within() + facet_wrap(scales = \"free_y\") + scale_y_reordered() combo to sort within facets.\r\nUsing override.aes argument to manipulate legend aesthetics after they’re generated by the geom_*()s\r\nUsing slice_max() instead of top_n() to catch up with the new {dplyr} update\r\nThings to improve\r\nFont sizing and image resolution\r\nPlacement and size of legend is sorta awkward.\r\nPlot feels too… empty. I think I treated this too much like a figure for a journal article. Maybe add some background color next time?\r\nCode\r\nAlso available on github\r\n\r\n\r\nlibrary(tidyverse)\r\nlibrary(tidytuesdayR)\r\nlibrary(lemon)\r\nlibrary(ggalt)\r\nlibrary(patchwork)\r\nlibrary(extrafont)\r\n\r\ntheme_set(theme_classic())\r\n\r\n### Data\r\n\r\ntuesdata <- tidytuesdayR::tt_load('2020-08-04')\r\n\r\nenergy_types <- tuesdata$energy_types\r\n\r\nenergy_types_tidy <- energy_types %>% \r\n pivot_longer(where(is.double), names_to = \"Year\", values_to = \"GWh\")\r\n\r\n\r\nplot_data <- energy_types_tidy %>% \r\n add_count(country, Year, wt = GWh, name = \"Total\") %>% \r\n mutate(GWh_prop = GWh/Total) %>% \r\n select(-country_name, -GWh, -Total , -level) %>% \r\n filter(Year %in% c(2016, 2018))\r\n \r\n\r\n### Plotting\r\n\r\np1 <- plot_data %>% \r\n filter(type == \"Conventional thermal\") %>% \r\n pivot_wider(names_from = Year, values_from = GWh_prop) %>% \r\n mutate(country = fct_reorder(country, `2018`, max, .desc = TRUE)) %>% \r\n mutate(increase = (`2018` - `2016`) > 0) %>% \r\n ggplot() +\r\n geom_dumbbell(\r\n aes(y = country, x = `2016`, xend = `2018`, color = increase),\r\n dot_guide = TRUE, dot_guide_size = 0.25,\r\n size = 2, colour_x = \"#babfb6\", colour_xend = \"#5f787b\"\r\n ) +\r\n scale_color_manual(values = c(\"#d69896\", \"#a1cf86\"), labels = c(\"2016\", \"2018\")) +\r\n guides(color = guide_legend(override.aes = list(color = c(\"#babfb6\", \"#5f787b\"), size = 3))) +\r\n labs(title = \"Conventional Thermal Energy\",\r\n y = \"Country Codes\",\r\n color = NULL) +\r\n theme(legend.position = c(.75, .85),\r\n axis.title.y = element_text(size = 12, vjust = 5))\r\n\r\np2 <- plot_data %>% \r\n filter(type != \"Conventional thermal\") %>% \r\n pivot_wider(names_from = Year, values_from = GWh_prop) %>% \r\n mutate(type = fct_lump(type, n = 3, w = `2018`)) %>% \r\n group_by(type, country) %>% \r\n summarize(`2016` = sum(`2016`), `2018` = sum(`2018`)) %>% \r\n slice_max(`2018`, n = 10, with_ties = FALSE) %>% \r\n mutate(country = tidytext::reorder_within(country, `2018`, type)) %>% \r\n mutate(increase = (`2018` - `2016`) > 0) %>% \r\n ggplot() +\r\n geom_dumbbell(\r\n aes(y = country, x = `2016`, xend = `2018`, color = increase),\r\n dot_guide = TRUE, dot_guide_size = .4,\r\n size = 2.5, colour_x = \"#babfb6\", colour_xend = \"#5f787b\",\r\n show.legend = FALSE\r\n ) +\r\n scale_color_manual(values = c(\"#d69896\", \"#a1cf86\")) +\r\n tidytext::scale_y_reordered() +\r\n facet_rep_wrap(~type, scales = \"free_y\") +\r\n labs(title = \"Clean Energy\",\r\n subtitle = \"Leaders in Each Category (Top 10)\",\r\n y = NULL)\r\n\r\npatched <- p1 + p2 &\r\n coord_capped_cart(bottom = \"both\") &\r\n scale_x_continuous(labels = scales::percent) &\r\n labs(x = NULL) &\r\n theme(\r\n plot.title = element_text(hjust = 0.5, size = 16, face = \"bold\"),\r\n text = element_text(family = \"Montserrat\"),\r\n panel.grid.major.y = element_blank(),\r\n plot.margin = unit(c(.4,.2,.2,.4), \"cm\"),\r\n plot.background = element_rect(color = \"transparent\")\r\n )\r\n\r\npatched + plot_annotation(title = \"Electricity Production in Europe\",\r\n subtitle = \"A comparison between 2016 and 2018\",\r\n caption = \"Percent Accounting for the Country's Total Electricity Generated\",\r\n theme = list(plot.title = element_text(size = 22),\r\n plot.subtitle = element_text(face = \"italic\", hjust = .5),\r\n plot.caption = element_text(size = 12, hjust = .5)))\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-08-04-tidytuesday-2020-week-32/preview.png", + "last_modified": "2020-11-01T19:46:26-05:00", + "input_file": {}, + "preview_width": 1444, + "preview_height": 805 + }, + { + "path": "posts/2020-07-29-six-years-of-my-spotify-playlists/", + "title": "Six years of my Spotify playlists", + "description": "An analysis of acoustic features with {spotifyr}", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-07-29", + "categories": [ + "ggplot2", + "gganimate", + "spotifyr", + "data wrangling", + "data visualization" + ], + "contents": "\r\n\r\nContents\r\nBackground\r\nAnalysis #1 - Size of monthly playlists over time\r\nAnalysis #2 - Audio features\r\nAnalysis #3 - Songs during college\r\nAnalysis #4 - “My Top 100” playlists\r\nConclusion\r\n\r\n\r\n\r\n\r\nBackground\r\nOne of my longest running habits is making monthly playlists. At the start of every month, I create a new playlist for that month and add songs that I like. Some songs are carried over from the previous month’s playlist and others are songs that I newly discover, but they’re all representative of the songs that I’m “into” for that month.\r\nI’ve been doing this for many years, and have the best record of my monthly playlists for the past 6 years, which is how long I’ve been using spotify. So when I saw people talking about {spotifyr} - an R wrapper for Spotify’s web API - on twitter, I decided to take a stab at analyzing my monthly playlists (code here).\r\n\r\n\r\n\r\n\r\nAnalysis #1 - Size of monthly playlists over time\r\nWhen I first pulled information about my Spotify account, I noticed that I had some gaps in my monthly playlists. This was a special case of non-random missing data: when I didn’t make a new playlist for the month, it’s because I didn’t think that there was a substantial change in what I’m jamming to from the previous month. The {zoo} package, which I didn’t know about before, came in very handy here for dealing with this missingness with its na.locf() (Last Observation Carried Forward) function.\r\nAfter some more cleaning steps, I first made a simple plot that counted the number of songs that each monthly playlist had.\r\n\r\nThere are some interesting things I notice, and here’s some context for them.\r\n2014, the year I began using Spotify, has high number of songs per playlist. This makes sense because the transition period involved a lot of transferring-over-in-bulk of my favorite music from iTunes (which I used previously).\r\nThe three consecutive months of missing playlists in 2017 was over a summer camp. I had forgotten about that until I started this analysis, but for that summer I just kept one playlist called “Summer 2017.”\r\nBoth the playlist with the most songs (78) and the playlist with the least songs (1) are in 2017. That was the year when I was exposed to a lot with different music genres from going to parties my friends. That was also my Sophomore year, which was a hot mess, but that’s a story for another time. You can get a better sense of my music taste being all over the place in the next section.\r\nMay 2017 was the month of sad azn vibes. My playlist had a single song, which was American Girl by Mitski and I think that says everythihng.\r\nIn November 2017, the month with the largest playlist, a friend who was known for having a great taste in music shared with me their playlist of 200+ EDM songs. I never really got into EDM previously but that was a gamechanger. I kind of went through an EDM phase for a short while after that, and November 2017 playlist is still the playlist I go back to when I want to listen to some good EDM.\r\nThe missing playlist of March 2020 was at perhaps the busiest time of my life - I was juggling my thesis, finals, grad school visits/decisions, finishing up my graduation requirements, moving out of campus back to Korea, and, of course, dealing with the pandemic. Makes sense why that month is missing its playlist.\r\nAnalysis #2 - Audio features\r\nThe real deal of Spotify API is actually the audio features, which Spotify calculates using their special algorithms. Some of the features are listed in the table below (adopted from the documentation). Of these, I decided to narrow down to acousticness, danceability, energy, and valence because others didn’t really show much variation (e.g., I don’t listen to live-recorded music on Spotify, so liveness is always near zero).\r\n\r\nhtml {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', 'Fira Sans', 'Droid Sans', Arial, sans-serif;\r\n}\r\n\r\n#yjhfkriyxi .gt_table {\r\n display: table;\r\n border-collapse: collapse;\r\n margin-left: auto;\r\n margin-right: auto;\r\n color: #333333;\r\n font-size: 16px;\r\n font-weight: normal;\r\n font-style: normal;\r\n background-color: #FFFFFF;\r\n width: auto;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #A8A8A8;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #A8A8A8;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_heading {\r\n background-color: #FFFFFF;\r\n text-align: center;\r\n border-bottom-color: #FFFFFF;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_title {\r\n color: #333333;\r\n font-size: 125%;\r\n font-weight: initial;\r\n padding-top: 4px;\r\n padding-bottom: 4px;\r\n border-bottom-color: #FFFFFF;\r\n border-bottom-width: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_subtitle {\r\n color: #333333;\r\n font-size: 85%;\r\n font-weight: initial;\r\n padding-top: 0;\r\n padding-bottom: 4px;\r\n border-top-color: #FFFFFF;\r\n border-top-width: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_bottom_border {\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_col_headings {\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_col_heading {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: normal;\r\n text-transform: inherit;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: bottom;\r\n padding-top: 5px;\r\n padding-bottom: 6px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n overflow-x: hidden;\r\n}\r\n\r\n#yjhfkriyxi .gt_column_spanner_outer {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: normal;\r\n text-transform: inherit;\r\n padding-top: 0;\r\n padding-bottom: 0;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n}\r\n\r\n#yjhfkriyxi .gt_column_spanner_outer:first-child {\r\n padding-left: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_column_spanner_outer:last-child {\r\n padding-right: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_column_spanner {\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n vertical-align: bottom;\r\n padding-top: 5px;\r\n padding-bottom: 6px;\r\n overflow-x: hidden;\r\n display: inline-block;\r\n width: 100%;\r\n}\r\n\r\n#yjhfkriyxi .gt_group_heading {\r\n padding: 8px;\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n text-transform: inherit;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: middle;\r\n}\r\n\r\n#yjhfkriyxi .gt_empty_group_heading {\r\n padding: 0.5px;\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n vertical-align: middle;\r\n}\r\n\r\n#yjhfkriyxi .gt_from_md > :first-child {\r\n margin-top: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_from_md > :last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n#yjhfkriyxi .gt_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n margin: 10px;\r\n border-top-style: solid;\r\n border-top-width: 1px;\r\n border-top-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: middle;\r\n overflow-x: hidden;\r\n}\r\n\r\n#yjhfkriyxi .gt_stub {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n text-transform: inherit;\r\n border-right-style: solid;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n padding-left: 12px;\r\n}\r\n\r\n#yjhfkriyxi .gt_summary_row {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n text-transform: inherit;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n#yjhfkriyxi .gt_first_summary_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_grand_summary_row {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n text-transform: inherit;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n#yjhfkriyxi .gt_first_grand_summary_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n border-top-style: double;\r\n border-top-width: 6px;\r\n border-top-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_striped {\r\n background-color: rgba(128, 128, 128, 0.05);\r\n}\r\n\r\n#yjhfkriyxi .gt_table_body {\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_footnotes {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n border-bottom-style: none;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_footnote {\r\n margin: 0px;\r\n font-size: 90%;\r\n padding: 4px;\r\n}\r\n\r\n#yjhfkriyxi .gt_sourcenotes {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n border-bottom-style: none;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#yjhfkriyxi .gt_sourcenote {\r\n font-size: 90%;\r\n padding: 4px;\r\n}\r\n\r\n#yjhfkriyxi .gt_left {\r\n text-align: left;\r\n}\r\n\r\n#yjhfkriyxi .gt_center {\r\n text-align: center;\r\n}\r\n\r\n#yjhfkriyxi .gt_right {\r\n text-align: right;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n\r\n#yjhfkriyxi .gt_font_normal {\r\n font-weight: normal;\r\n}\r\n\r\n#yjhfkriyxi .gt_font_bold {\r\n font-weight: bold;\r\n}\r\n\r\n#yjhfkriyxi .gt_font_italic {\r\n font-style: italic;\r\n}\r\n\r\n#yjhfkriyxi .gt_super {\r\n font-size: 65%;\r\n}\r\n\r\n#yjhfkriyxi .gt_footnote_marks {\r\n font-style: italic;\r\n font-size: 65%;\r\n}\r\nFeature\r\n Description\r\n acousticness\r\n A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.\r\n danceability\r\n Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.\r\n energy\r\n Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.\r\n instrumentalness\r\n Predicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.\r\n liveness\r\n Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.\r\n loudness\r\n The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.\r\n speechiness\r\n Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.\r\n tempo\r\n The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.\r\n valence\r\n A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).\r\n \r\n\r\nI was interested in looking at how my music taste changed over time, so for each monthly playlist, I calculated the mean values for these four features and made a line plot:\r\n\r\nSome things that pop out:\r\nOverall, I tend to listen to bright music (high dancibility and energy) but there is still a lot of variation (especially in valence).\r\nAcousticness stays pretty low and doesn’t seem to correlate much with time. This makes sense because I primarily listen to pop and electric songs, which are both very far from sounding acoustic.\r\nThe one dip in May 2017 is, you guessed it, that playlist with just that one Mitski song. That was the only playlist where the mean danceability and energy values are below 0.5.\r\nIt also looks like I listen to brighter music with every passing year, though this trend is subtle. This it’s a bit easier to see in the animation below (especially for energy and valence).\r\n\r\nAnalysis #3 - Songs during college\r\nNext, I wanted to focus on my years in college, from Fall 2016 to Spring 2020. For this analysis, I defined time in terms of school years and quarters. While I was a college student, I often felt like the passage of time was defined in terms of quarters, so this scale felt appropriate.\r\nHere is the same line plot, except the feature values are averaged by quarter instead of month, and the plot is now faceted by school year:\r\n\r\nObservations:\r\nThe trend in increasing positivity can be observed in this plot as well (with my Junior year coming out on top).\r\nI was actually wondering whether I’d see a pattern by quarter, but there doesn’t seem to be any strong ones.\r\nAnalysis #4 - “My Top 100” playlists\r\nIn my last analysis, I move from my monthly playlists to the end-of-the-year playlists that Spotify makes for you every year.\r\nFor this, I grabbed audio features of songs in my yearly top 100 playlists from 2016-2019. In this graph, each line represents a song and the top 10 most listened to song of each year are emphasized in black. The thick red line in each panel represents the average of the songs for that year.\r\n\r\nSome observations on the variation in audio features among my top 100 playlists:\r\nAlthough the monthly averages in the previous graphs showed extremely low acousticness values (never going above 0.5), that actually hid a lot of variation. You can see that a good number of songs with high acousticness make it to my top 100 (and sometimes even top 10) songs, but that number seems to gradually decline over time. The song with highest acousticness, Ripchord by Rilo Kiley comes from my 2016 playlist. Rilo Kiley is an indie rock band that had a strong influence on my music taste during high school, so it’s no surprise that this song made it there.\r\nThere’s also a trend of decreasing overall variability in the audio features of my top 100 songs. Perhaps this means that I’m narrowing in on my true music taste? Or maybe that I’m going through a phase in music taste? It’s kind of hard to tell but interesting nonetheless.\r\nConclusion\r\nI didn’t really dig too deeply into the acoustic profile of the songs I listen to in this post, and I doubt that Spotify’s list of audio features are comprehensive enough to describe my music taste, but this was a cool exercise!\r\nAnd although I ignored several of the audio features because they weren’t very informative for the songs I listen to, I thought I should at least leave a summary table showing the mean values for all features that I gave in the table above!\r\n\r\nhtml {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', 'Fira Sans', 'Droid Sans', Arial, sans-serif;\r\n}\r\n\r\n#xmhaddpekd .gt_table {\r\n display: table;\r\n border-collapse: collapse;\r\n margin-left: auto;\r\n margin-right: auto;\r\n color: #333333;\r\n font-size: 16px;\r\n font-weight: normal;\r\n font-style: normal;\r\n background-color: #FFFFFF;\r\n width: auto;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #A8A8A8;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #A8A8A8;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_heading {\r\n background-color: #FFFFFF;\r\n text-align: center;\r\n border-bottom-color: #FFFFFF;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_title {\r\n color: #333333;\r\n font-size: 125%;\r\n font-weight: initial;\r\n padding-top: 4px;\r\n padding-bottom: 4px;\r\n border-bottom-color: #FFFFFF;\r\n border-bottom-width: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_subtitle {\r\n color: #333333;\r\n font-size: 85%;\r\n font-weight: initial;\r\n padding-top: 0;\r\n padding-bottom: 4px;\r\n border-top-color: #FFFFFF;\r\n border-top-width: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_bottom_border {\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_col_headings {\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_col_heading {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: normal;\r\n text-transform: inherit;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: bottom;\r\n padding-top: 5px;\r\n padding-bottom: 6px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n overflow-x: hidden;\r\n}\r\n\r\n#xmhaddpekd .gt_column_spanner_outer {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: normal;\r\n text-transform: inherit;\r\n padding-top: 0;\r\n padding-bottom: 0;\r\n padding-left: 4px;\r\n padding-right: 4px;\r\n}\r\n\r\n#xmhaddpekd .gt_column_spanner_outer:first-child {\r\n padding-left: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_column_spanner_outer:last-child {\r\n padding-right: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_column_spanner {\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n vertical-align: bottom;\r\n padding-top: 5px;\r\n padding-bottom: 6px;\r\n overflow-x: hidden;\r\n display: inline-block;\r\n width: 100%;\r\n}\r\n\r\n#xmhaddpekd .gt_group_heading {\r\n padding: 8px;\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n text-transform: inherit;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: middle;\r\n}\r\n\r\n#xmhaddpekd .gt_empty_group_heading {\r\n padding: 0.5px;\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n vertical-align: middle;\r\n}\r\n\r\n#xmhaddpekd .gt_from_md > :first-child {\r\n margin-top: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_from_md > :last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n#xmhaddpekd .gt_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n margin: 10px;\r\n border-top-style: solid;\r\n border-top-width: 1px;\r\n border-top-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 1px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 1px;\r\n border-right-color: #D3D3D3;\r\n vertical-align: middle;\r\n overflow-x: hidden;\r\n}\r\n\r\n#xmhaddpekd .gt_stub {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n font-size: 100%;\r\n font-weight: initial;\r\n text-transform: inherit;\r\n border-right-style: solid;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n padding-left: 12px;\r\n}\r\n\r\n#xmhaddpekd .gt_summary_row {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n text-transform: inherit;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n#xmhaddpekd .gt_first_summary_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_grand_summary_row {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n text-transform: inherit;\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n}\r\n\r\n#xmhaddpekd .gt_first_grand_summary_row {\r\n padding-top: 8px;\r\n padding-bottom: 8px;\r\n padding-left: 5px;\r\n padding-right: 5px;\r\n border-top-style: double;\r\n border-top-width: 6px;\r\n border-top-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_striped {\r\n background-color: rgba(128, 128, 128, 0.05);\r\n}\r\n\r\n#xmhaddpekd .gt_table_body {\r\n border-top-style: solid;\r\n border-top-width: 2px;\r\n border-top-color: #D3D3D3;\r\n border-bottom-style: solid;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_footnotes {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n border-bottom-style: none;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_footnote {\r\n margin: 0px;\r\n font-size: 90%;\r\n padding: 4px;\r\n}\r\n\r\n#xmhaddpekd .gt_sourcenotes {\r\n color: #333333;\r\n background-color: #FFFFFF;\r\n border-bottom-style: none;\r\n border-bottom-width: 2px;\r\n border-bottom-color: #D3D3D3;\r\n border-left-style: none;\r\n border-left-width: 2px;\r\n border-left-color: #D3D3D3;\r\n border-right-style: none;\r\n border-right-width: 2px;\r\n border-right-color: #D3D3D3;\r\n}\r\n\r\n#xmhaddpekd .gt_sourcenote {\r\n font-size: 90%;\r\n padding: 4px;\r\n}\r\n\r\n#xmhaddpekd .gt_left {\r\n text-align: left;\r\n}\r\n\r\n#xmhaddpekd .gt_center {\r\n text-align: center;\r\n}\r\n\r\n#xmhaddpekd .gt_right {\r\n text-align: right;\r\n font-variant-numeric: tabular-nums;\r\n}\r\n\r\n#xmhaddpekd .gt_font_normal {\r\n font-weight: normal;\r\n}\r\n\r\n#xmhaddpekd .gt_font_bold {\r\n font-weight: bold;\r\n}\r\n\r\n#xmhaddpekd .gt_font_italic {\r\n font-style: italic;\r\n}\r\n\r\n#xmhaddpekd .gt_super {\r\n font-size: 65%;\r\n}\r\n\r\n#xmhaddpekd .gt_footnote_marks {\r\n font-style: italic;\r\n font-size: 65%;\r\n}\r\nFeature\r\n Description\r\n Average\r\n acousticness\r\n A confidence measure from 0.0 to 1.0 of whether the track is acoustic. 1.0 represents high confidence the track is acoustic.\r\n 0.16\r\n danceability\r\n Danceability describes how suitable a track is for dancing based on a combination of musical elements including tempo, rhythm stability, beat strength, and overall regularity. A value of 0.0 is least danceable and 1.0 is most danceable.\r\n 0.64\r\n energy\r\n Energy is a measure from 0.0 to 1.0 and represents a perceptual measure of intensity and activity. Typically, energetic tracks feel fast, loud, and noisy. For example, death metal has high energy, while a Bach prelude scores low on the scale. Perceptual features contributing to this attribute include dynamic range, perceived loudness, timbre, onset rate, and general entropy.\r\n 0.75\r\n instrumentalness\r\n Predicts whether a track contains no vocals. “Ooh” and “aah” sounds are treated as instrumental in this context. Rap or spoken word tracks are clearly “vocal”. The closer the instrumentalness value is to 1.0, the greater likelihood the track contains no vocal content. Values above 0.5 are intended to represent instrumental tracks, but confidence is higher as the value approaches 1.0.\r\n 0.02\r\n liveness\r\n Detects the presence of an audience in the recording. Higher liveness values represent an increased probability that the track was performed live. A value above 0.8 provides strong likelihood that the track is live.\r\n 0.19\r\n loudness\r\n The overall loudness of a track in decibels (dB). Loudness values are averaged across the entire track and are useful for comparing relative loudness of tracks. Loudness is the quality of a sound that is the primary psychological correlate of physical strength (amplitude). Values typical range between -60 and 0 db.\r\n -4.95\r\n speechiness\r\n Speechiness detects the presence of spoken words in a track. The more exclusively speech-like the recording (e.g. talk show, audio book, poetry), the closer to 1.0 the attribute value. Values above 0.66 describe tracks that are probably made entirely of spoken words. Values between 0.33 and 0.66 describe tracks that may contain both music and speech, either in sections or layered, including such cases as rap music. Values below 0.33 most likely represent music and other non-speech-like tracks.\r\n 0.08\r\n tempo\r\n The overall estimated tempo of a track in beats per minute (BPM). In musical terminology, tempo is the speed or pace of a given piece and derives directly from the average beat duration.\r\n 120.25\r\n valence\r\n A measure from 0.0 to 1.0 describing the musical positiveness conveyed by a track. Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), while tracks with low valence sound more negative (e.g. sad, depressed, angry).\r\n 0.55\r\n \r\n\r\n\r\n\r\n\r\n", + "preview": "posts/2020-07-29-six-years-of-my-spotify-playlists/preview.png", + "last_modified": "2020-11-01T19:47:08-05:00", + "input_file": {}, + "preview_width": 3593, + "preview_height": 2459 + }, + { + "path": "posts/2020-07-20-shiny-tips-1/", + "title": "Shiny tips - the first set", + "description": "%||%, imap() + {shinybusy}, and user inputs in modalDialog()", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-07-20", + "categories": [ + "shiny" + ], + "contents": "\r\n\r\n\r\n\r\nWhen I was an RA in the LEARN lab - a child language development lab at Northwestern - I worked on a shiny app that automates snowball search for meta-analysis research (relevant research poster). Long story short, I worked on it for a couple months, got it working, then stopped working on it for another couple months, and had the chance to revisit it just recently.\r\nWhen I picked the project back up, I realized that my old code was poorly commented, somewhat inefficient, and even hackish at times. So I decided to re-write it from scratch. In this second time around, I learned a lot of useful functions/tricks that really helped streamline my code and I thought I’d document my three favorite ones here for future reference.\r\n1. %||% from {rlang}\r\nBasically, %||% is an infix operator that returns the left-hand side when it is not Null and the right-hand side when it is Null. It’s from the {rlang} package but you can also define the function yourself:\r\n\r\n\r\n\"%||%\" <- function(lhs, rhs) {\r\n if (is.null(lhs)) rhs else lhs\r\n}\r\n\r\na <- 10\r\nb <- NULL\r\n\r\na %||% b\r\n\r\n\r\n [1] 10\r\n\r\nb %||% a\r\n\r\n\r\n [1] 10\r\n\r\n# note how the output is different when b is no longer null\r\nb <- 11\r\nb %||% a\r\n\r\n\r\n [1] 11\r\n\r\nI found this operator to be extremely useful when displaying empty tables as placeholders when using DT::datatable(). It allows me to communicate to the user where a table is expected to appear rather than just not showing anything at all when no data is loaded (which is what happens by default).\r\nFor example, if you want to show an empty column with an empty row when the data (here, the reactive variable mydf) is null, you might do the following:\r\n\r\n\r\nmydf_display <- renderDataTable({\r\n datatable(mydf() %||% tibble(` ` = NA))\r\n})\r\n\r\n\r\n\r\nAnother use-case for %||% is when I’m trying a sequence of function calls until one one of them succeeds and returns a non-null value. For example, say I want to scrape some information online and I have API wrappers for different websites that potentially have that information. I can chain them together using %||% like so:\r\n\r\n\r\nmyinfo <- \r\n scrape_website1() %||%\r\n scrape_website2() %||%\r\n scrape_website3()\r\n\r\n\r\n\r\nThis is much neater than nested if…else statements!\r\n2. purrr::imap() and {shinybusy}\r\nUsing my shiny app involves a lot of waiting (querying online databases), so I looked into ways to show a progress bar similar to the family of *Modal() functions from {shiny}. The extension package {shinybusy} (project site) offers a very satisfying solution to this problem.\r\nBasically, you initialize a progress bar with show_modal_progress_*() and increment its value inside whatever operation you’re doing. Here’s a pseudo code demonstrating how it works:\r\n\r\ninitialize a progress bar\r\n\r\ncreate a new_list of same size to store output\r\n\r\nfor index in seq_along(list):\r\n new_list[index] <- calculations(list[index])\r\n increment progress bar by index\r\n \r\nremove progress bar\r\n\r\nreturn new_list\r\n\r\nBut in my case, my “do stuff” part didn’t involve a big wall of code because I packed it into a single function in a separate file that I source at the beginning. This, coupled with my general aversion to for-loops, drove me to imap() and its variants from {purrr}. imap() is like map() except it also keeps track of the index of the element that you’re operating on (to put it another way, it’s like map2() where .y is the index).\r\nNow, you don’t need an explicit for-loop to increment and the above code can be reduced to this:\r\n\r\ninitialize a progress bar\r\n\r\nnew_list <- imap(list,\r\n ~{\r\n calculations(.x)\r\n increment progress bar by .y\r\n })\r\n \r\nremove progress bar\r\n\r\nreturn new_list\r\n\r\nIn my opinion, this is much cleaner! For a more concrete example, here’s a template using actual code:\r\n\r\n\r\nmy_data <- eventReactive(input$my_button, {\r\n \r\n # initialize a progress bar\r\n show_modal_progress_line()\r\n \r\n # do operation on elements of vector\r\n result <- imap(my_reactive_var(),\r\n ~{\r\n update_modal_progress(value = .y / length(my_reactive_var()))\r\n my_operation_on_element(.x)\r\n })\r\n \r\n # remove progress bar\r\n remove_modal_progress()\r\n \r\n # return output\r\n return(result)\r\n \r\n})\r\n\r\n\r\n\r\n3. User inputs inside modalDialog()\r\nIn {shiny}, you can show the user a pop-up message box by first laying out the content of the message in modalDialog() and then rendering it with showModal(). In the first version of my app, I used this to show simple messages like warnings, but did you know that you can include any *Input widgets too?\r\nFor example, this code renders a pop-up box for a file upload in response to a button click:\r\n\r\n\r\nobserveEvent(input$MyButton, {\r\n showModal(modalDialogue(\r\n title = \"Upload File Here\",\r\n fileInput(inputID = \"UploadedFile\", label = \"Upload\")\r\n ))\r\n})\r\n\r\n\r\n\r\nAnd you can access whatever is uploaded using input$UploadedFile like you would if the file upload widget was in the ui side of the app!\r\nThis took me a bit to get used to because you are defining the modal in the server side where the content of the modal looks like the ui side but can be accessed back at the server side. But this was life-changing and it opened up a lot of potential for my GUI to be less cluttered. Using this neat trick, I was able to move a large feature into a modal that would only be available upon a click of a button (it was a feature designed for a rare case scenario so I thought I’d save the user from having to see the entire interface for that if they don’t ask for it).\r\nEnding note\r\nThe more I learn and use shiny, the less I feel like I know. I’m actually enjoying this stage of my progress because every new thing just absolutely wows me (and I hope to continue sharing what I learn - hence this being the “first set”). And very much looking forward to Hadley Wickham’s new book on shiny!\r\n\r\n\r\n\r\n", + "preview": "posts/2020-07-20-shiny-tips-1/preview.png", + "last_modified": "2020-11-01T19:47:55-05:00", + "input_file": {}, + "preview_width": 746, + "preview_height": 133 + }, + { + "path": "posts/2020-07-13-geom-paired-raincloud/", + "title": "geom_paired_raincloud()", + "description": "A {ggplot2} geom for visualizing change in distribution between two conditions.", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-07-13", + "categories": [ + "data visualization", + "ggplot2" + ], + "contents": "\r\n\r\n\r\n\r\nRaincloud Plots\r\n\r\n\r\n\r\nGeoms for rainplots (a.k.a. split violin plots) already exist, but you might have a very special case where you have pairs of rainplots and you want to track the change in individual datapoints between the rainplot distributions.\r\nFor example, say you want to track the height of a plant species across two timepoints and you want to communicate three information:\r\nThe change in the distribution of plant heights between timepoints.\r\nThe individual variation in height (“intercept”).\r\nThe individual variation in change of height between timepoints (“slope”).\r\nAnd the data looks like this:\r\n\r\n\r\nset.seed(1234)\r\nplants <- tibble(Species = \"Dwarf\",\r\n Plant = rep(factor(1:100), 2),\r\n Timepoint = rep(c(\"First\", \"Second\"), each = 100),\r\n Height = c(rnorm(100, 10, 5), rnorm(100, 20, 8)))\r\n\r\nplants %>% \r\n group_by(Timepoint) %>% \r\n summarize(across(Height, list(mean = mean, sd = sd), .names = \"{col}_{fn}\"))\r\n\r\n\r\n # A tibble: 2 x 3\r\n Timepoint Height_mean Height_sd\r\n \r\n 1 First 9.22 5.02\r\n 2 Second 20.3 8.26\r\n\r\nYou can use geom_violhalf() from the {see} package to do this:\r\n\r\n\r\nlibrary(see)\r\nggplot(plants, aes(Timepoint, Height, fill = Timepoint)) +\r\n geom_violinhalf() +\r\n geom_point(aes(group = Plant),\r\n position = position_nudge(-.05),\r\n alpha = 0.5, shape = 16) +\r\n geom_line(aes(group = Plant),\r\n position = position_nudge(-.05))\r\n\r\n\r\n\r\n\r\nBut it’d look better if the lines don’t cross over the raincloud for the first timepoint.\r\ngeom_paired_raincloud() automatically flips the first raincloud for you! You do get a warining that there are overlapping points, but that’s because the x-axis is categorical and {ggplot2} thinks that flipping the raincloud intrudes into a different category. AFAIK you don’t lose any data despite this warning, but you should double check to be sure.\r\n\r\n\r\ndevtools::source_url(\"https://raw.githubusercontent.com/yjunechoe/geom_paired_raincloud/master/geom_paired_raincloud.R\")\r\n\r\nggplot(plants, aes(Timepoint, Height, fill = Timepoint)) +\r\n geom_paired_raincloud()\r\n\r\n\r\n Warning: position_dodge requires non-overlapping x intervals\r\n\r\n\r\nWe can add individual points and lines onto this plot in a similar way, except you need to use a 2-length vector for position_dodge().\r\n\r\n\r\nplants %>% \r\n # arrange by individual plant\r\n arrange(Plant) %>% \r\n ggplot(aes(Timepoint, Height, fill = Timepoint)) +\r\n geom_paired_raincloud() +\r\n geom_point(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05)),\r\n alpha = 0.5, shape = 16,\r\n show.legend = FALSE) +\r\n geom_line(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05)))\r\n\r\n\r\n\r\n\r\nNOTE: you need to make sure that the data is arranged by the variable you’re using for the group aesthetic (in this case, Plant) before being passed into ggplot() for position_nudge() in the other geoms to work properly (sorry it’s a bit hacky):\r\ngeom_paired_raincloud works as long as the grouping is of length two (i.e., as long as you’re comparing distribution between two levels).\r\nLet’s modify the plants dataset to include another species of plant:\r\n\r\n\r\nplants2 <- plants %>% \r\n bind_rows(\r\n tibble(Species = \"Giant\",\r\n Plant = rep(factor(101:200), 2),\r\n Timepoint = rep(c(\"First\", \"Second\"), each = 100),\r\n Height = c(rnorm(100, 30, 5), rnorm(100, 50, 8)))\r\n )\r\n\r\nplants2 %>% \r\n group_by(Species, Timepoint) %>% \r\n summarize(across(Height, list(mean = mean, sd = sd), .names = \"{col}_{fn}\"))\r\n\r\n\r\n # A tibble: 4 x 4\r\n # Groups: Species [2]\r\n Species Timepoint Height_mean Height_sd\r\n \r\n 1 Dwarf First 9.22 5.02\r\n 2 Dwarf Second 20.3 8.26\r\n 3 Giant First 30.8 4.80\r\n 4 Giant Second 49.9 8.40\r\n\r\nIn this new plot, I just added facet_wrap(~Species)\r\n\r\n\r\nplants2 %>% \r\n arrange(Plant) %>% \r\n ggplot(aes(Timepoint, Height, fill = Timepoint)) +\r\n geom_paired_raincloud() +\r\n geom_point(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05)),\r\n alpha = 0.5, shape = 16,\r\n show.legend = FALSE) +\r\n geom_line(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05))) +\r\n facet_wrap(~Species)\r\n\r\n\r\n\r\n\r\ngeom_paired_raincloud() isn’t particularly useful for plotting comparisons between more than two levels, so it throws a warning when that’s the case:\r\n\r\n\r\n# Adding a third timepoint\r\nplants3 <- plants %>% \r\n bind_rows(tibble(Species = \"Dwarf\",\r\n Plant = factor(1:100),\r\n Timepoint = \"Third\",\r\n Height = rnorm(100, 40, 10)))\r\n\r\nplants3 %>% \r\n group_by(Timepoint) %>% \r\n summarize(across(Height, list(mean = mean, sd = sd), .names = \"{col}_{fn}\"))\r\n\r\n\r\n # A tibble: 3 x 3\r\n Timepoint Height_mean Height_sd\r\n \r\n 1 First 9.22 5.02\r\n 2 Second 20.3 8.26\r\n 3 Third 39.8 11.2\r\n\r\n\r\n\r\nplants3 %>% \r\n arrange(Plant) %>% \r\n ggplot(aes(Timepoint, Height, fill = Timepoint)) +\r\n geom_paired_raincloud() +\r\n geom_point(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05)),\r\n alpha = 0.5, shape = 16,\r\n show.legend = FALSE) +\r\n geom_line(aes(group = Plant),\r\n position = position_nudge(c(.05, -.05)))\r\n\r\n\r\n\r\n\r\nBut I think geom_paired_raincloud() works great if you have the right data. Here’s an example from my recent work, looking at the variation in how subjects respond to stimuli when they’re presented in one condition (Subject Accent) compared to the other (Verb Accent).\r\n\r\n\r\n\r\nThe above plot is a combination of geom_paired_raincloud(), geom_point(), geom_line(), and geom_boxplot(). I like that you can employ all these aesthetics at once without making the plot too overwhelming. I’ve included the important part of the code here and the full code is available at the github repo for this research project.\r\n\r\n\r\nrainplot_data %>% \r\n ggplot(aes(x = Cond, y = z_RT, fill = Cond)) +\r\n geom_paired_raincloud(alpha = .5) +\r\n geom_point(aes(group = Item),\r\n position = position_nudge(c(.15, -.15)),\r\n alpha = .5, shape = 16) +\r\n geom_line(aes(group = Item),\r\n position = position_nudge(c(.13, -.13)),\r\n linetype = 3) +\r\n geom_boxplot(position = position_nudge(c(.07, -.07)),\r\n alpha = .5, width = .04, outlier.shape = \" \") +\r\n facet_wrap(~Type, scales = \"free_x\") +\r\n ...\r\n\r\n\r\n\r\n\r\nNotice how I use position_nudge() to make sure that the points, lines, and boxplots are side-by-side and not overlapping with each other.\r\n\r\n\r\n\r\n", + "preview": "posts/2020-07-13-geom-paired-raincloud/preview.png", + "last_modified": "2020-11-01T19:48:46-05:00", + "input_file": {}, + "preview_width": 7086, + "preview_height": 4251 + }, + { + "path": "posts/2020-06-30-treemap-with-ggplot/", + "title": "Plotting treemaps with {treemap} and {ggplot2}", + "description": "Using underlying plot data for maximum customization", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-06-30", + "categories": [ + "data visualization", + "treemap", + "ggplot2", + "tutorial" + ], + "contents": "\r\n\r\n\r\n\r\nTo steal the definition from Wikipedia, a treemap is used for “displaying hierarchical data using nested figures, usually rectangles.” There are lots of ways to make one in R, but I didn’t find any one existing solution appealing.\r\nFor illustration, let’s take the pokemon dataset from {highcharter} and plot a treemap with it using different methods.\r\n\r\n\r\n\r\n\r\n\r\ndata(\"pokemon\", package = \"highcharter\")\r\n\r\n# Cleaning up data for a treemap\r\ndata <- pokemon %>% \r\n select(pokemon, type_1, type_2, color_f) %>%\r\n mutate(type_2 = ifelse(is.na(type_2), paste(\"only\", type_1), type_2)) %>% \r\n group_by(type_1, type_2, color_f) %>% \r\n count(type_1, type_2) %>% \r\n ungroup()\r\n\r\nhead(data, 5)\r\n\r\n\r\n\r\ntype_1\r\n\r\n\r\ntype_2\r\n\r\n\r\ncolor_f\r\n\r\n\r\nn\r\n\r\n\r\nbug\r\n\r\n\r\nelectric\r\n\r\n\r\n#BBBD23\r\n\r\n\r\n2\r\n\r\n\r\nbug\r\n\r\n\r\nfighting\r\n\r\n\r\n#AD9721\r\n\r\n\r\n1\r\n\r\n\r\nbug\r\n\r\n\r\nfire\r\n\r\n\r\n#B9AA23\r\n\r\n\r\n2\r\n\r\n\r\nbug\r\n\r\n\r\nflying\r\n\r\n\r\n#A8AE52\r\n\r\n\r\n13\r\n\r\n\r\nbug\r\n\r\n\r\nghost\r\n\r\n\r\n#9AA03D\r\n\r\n\r\n1\r\n\r\n\r\n \r\n1. {treemap}\r\nHere’s a plot made from the {treemap} package:\r\n\r\n\r\nlibrary(treemap)\r\n\r\ntreemap(dtf = data,\r\n index = c(\"type_1\", \"type_2\"),\r\n vSize = \"n\",\r\n vColor = \"type_1\")\r\n\r\n\r\n\r\n\r\nIt actually doesn’t look too bad, but this package hasn’t been updated for 3 years and there aren’t a lot of options for customization. For the options that do exist, they’re a big list of additional arguments to the main workhorse function, treemap(), which feels a bit restrictive if you’re used to {ggplot}’s modular and layered grammar. So while it’s very simple to use, I’d probably use it only for exploring the data for myself.\r\n \r\n2. {highcharter}\r\nAll the way on the other side of this ease<—>customizability spectrum is {highcharter} which is arguably the most powerful data visualization package in R.\r\nWith highcharter, you can turn the previous graph into the following:\r\n\r\nThis looks much better, and it’s even interactive (although this particular one isn’t because I just copy pasted the image from this blog post from 2018). I’d use {highcharter} except that there isn’t a great documentation on plotting treemaps, and it definitely doesn’t help that {highcharter} has a pretty steep learning curve, even if you have a lot of experience with {ggplot2}.\r\nThe main problem I ran into is that the function hc_add_series_treemap() that was used to create the above graph is now depreciated. It redirects you to use hctreemap() which itself is also depreciated. That finally redirects you to use hctreemap2() which is pretty sparse in documentation and use-cases, and overall not very transparent IMO.\r\n \r\n3. {treemapify}\r\n{treemapify} is a ggplot solution to plotting treemaps.\r\nHere’s a plot of the pokemon dataset, adopting the example code from the vignette. Since it follows the layered grammar of ggplot, I figured I’d show what each of the four layers outlined in the code does:\r\n\r\n\r\nlibrary(treemapify)\r\n\r\nggplot(data, aes(area = n, fill = color_f, label = type_2,\r\n subgroup = type_1)) +\r\n # 1. Draw type_2 borders and fill colors\r\n geom_treemap() +\r\n # 2. Draw type_1 borders\r\n geom_treemap_subgroup_border() +\r\n # 3. Print type_1 text\r\n geom_treemap_subgroup_text(place = \"centre\", grow = T, alpha = 0.5, colour = \"black\",\r\n fontface = \"italic\", min.size = 0) +\r\n # 4. Print type_2 text\r\n geom_treemap_text(colour = \"white\", place = \"topleft\", reflow = T) +\r\n theme(legend.position = 0)\r\n\r\n\r\n\r\ngeom_treemap() draws type_2 borders and fill colors\r\n\r\n\r\n\r\ngeom_treemap_subgroup_border() draws type_1 borders\r\n\r\n\r\n\r\ngeom_treemap_subgroup_text() prints type_1 text\r\n\r\n\r\n\r\ngeom_treemap_text() prints type_2 text\r\n\r\n\r\n\r\nI find this the most appealing out of the three options and I do recommend this package, but I’m personally a bit hesistant to use it for three reasons:\r\nI don’t want to learn a whole ’nother family of geom_*s just to plot treemaps.\r\nSome of the ggplot “add-ons” that I like don’t really transfer over. For example, I can’t use geom_text_repel() from {ggrepel} because I have to use {treemapify}’s own text geoms like geom_treemap_subgroup_text() and geom_treemap_text().\r\nCustomization options are kind of a mouthful, and I’ve yet to see a nice-looking treemap that was plotted using this package. There are a couple example treemaps in the vignette but none of them look particularly good. An independently produced example here doesn’t look super great either.\r\n \r\nA Mixed (Hack-ish?) Solution\r\nBasically, I’m very lazy and I want to avoid learning any new packages or functions as much as possible.\r\nI’ve come up with a very simple solution to my self-created problem, which is to draw treemaps using geom_rect() with a little help from the {treemap} package introduced earlier.\r\nSo apparently, there’s a cool feature in treemap::treemap() where you can extract the plotting data.\r\nYou can do this by pulling the tm object from the plot function side-effect, and the underlying dataframe used for plotting looks like this.1:\r\n\r\n\r\ntm <- treemap(\r\n dtf = data,\r\n index = c(\"type_1\", \"type_2\"),\r\n vSize = \"n\",\r\n vColor = \"color_f\",\r\n type = 'color' # {treemap}'s equivalent of scale_fill_identity()\r\n)\r\n\r\n\r\n\r\nhead(tm$tm)\r\n\r\n\r\n\r\ntype_1\r\n\r\n\r\ntype_2\r\n\r\n\r\nvSize\r\n\r\n\r\nvColor\r\n\r\n\r\nstdErr\r\n\r\n\r\nvColorValue\r\n\r\n\r\nlevel\r\n\r\n\r\nx0\r\n\r\n\r\ny0\r\n\r\n\r\nw\r\n\r\n\r\nh\r\n\r\n\r\ncolor\r\n\r\n\r\nbug\r\n\r\n\r\nelectric\r\n\r\n\r\n2\r\n\r\n\r\n#BBBD23\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.4556639\r\n\r\n\r\n0.3501299\r\n\r\n\r\n0.0319174\r\n\r\n\r\n0.0872727\r\n\r\n\r\n#BBBD23\r\n\r\n\r\nbug\r\n\r\n\r\nfighting\r\n\r\n\r\n1\r\n\r\n\r\n#AD9721\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.4556639\r\n\r\n\r\n0.3064935\r\n\r\n\r\n0.0319174\r\n\r\n\r\n0.0436364\r\n\r\n\r\n#AD9721\r\n\r\n\r\nbug\r\n\r\n\r\nfire\r\n\r\n\r\n2\r\n\r\n\r\n#B9AA23\r\n\r\n\r\n2\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.4875812\r\n\r\n\r\n0.3501299\r\n\r\n\r\n0.0319174\r\n\r\n\r\n0.0872727\r\n\r\n\r\n#B9AA23\r\n\r\n\r\nbug\r\n\r\n\r\nflying\r\n\r\n\r\n13\r\n\r\n\r\n#A8AE52\r\n\r\n\r\n13\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.2757660\r\n\r\n\r\n0.2628571\r\n\r\n\r\n0.1160631\r\n\r\n\r\n0.1560000\r\n\r\n\r\n#A8AE52\r\n\r\n\r\nbug\r\n\r\n\r\nghost\r\n\r\n\r\n1\r\n\r\n\r\n#9AA03D\r\n\r\n\r\n1\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.4556639\r\n\r\n\r\n0.2628571\r\n\r\n\r\n0.0319174\r\n\r\n\r\n0.0436364\r\n\r\n\r\n#9AA03D\r\n\r\n\r\nbug\r\n\r\n\r\ngrass\r\n\r\n\r\n6\r\n\r\n\r\n#9CBB2B\r\n\r\n\r\n6\r\n\r\n\r\nNA\r\n\r\n\r\n2\r\n\r\n\r\n0.4744388\r\n\r\n\r\n0.4374026\r\n\r\n\r\n0.0450598\r\n\r\n\r\n0.1854545\r\n\r\n\r\n#9CBB2B\r\n\r\n\r\nWe can simply use this data to recreate the treemap that was made with {treemapify} - except this time we have more flexibility!\r\nFirst, we do some data cleaning:\r\n\r\n\r\ntm_plot_data <- tm$tm %>% \r\n # calculate end coordinates with height and width\r\n mutate(x1 = x0 + w,\r\n y1 = y0 + h) %>% \r\n # get center coordinates for labels\r\n mutate(x = (x0+x1)/2,\r\n y = (y0+y1)/2) %>% \r\n # mark primary groupings and set boundary thickness\r\n mutate(primary_group = ifelse(is.na(type_2), 1.2, .5)) %>% \r\n # remove colors from primary groupings (since secondary is already colored)\r\n mutate(color = ifelse(is.na(type_2), NA, color))\r\n\r\n\r\n\r\nThen we plot. It looks like I can recreate a lot of it with a little help from the {ggfittext} package that was in the source code2:\r\n\r\n\r\nggplot(tm_plot_data, aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1)) + \r\n # add fill and borders for groups and subgroups\r\n geom_rect(aes(fill = color, size = primary_group),\r\n show.legend = FALSE, color = \"black\", alpha = .3) +\r\n scale_fill_identity() +\r\n # set thicker lines for group borders\r\n scale_size(range = range(tm_plot_data$primary_group)) +\r\n # add labels\r\n ggfittext::geom_fit_text(aes(label = type_2), min.size = 1) +\r\n # options\r\n scale_x_continuous(expand = c(0, 0)) +\r\n scale_y_continuous(expand = c(0, 0)) +\r\n theme_void()\r\n\r\n\r\n\r\n\r\nNow, I can be a lot more flexible with my customizations.\r\nFor example, let’s say I wanted to isolate and emphasize the secondary types that have unique type-combinations with steel, AND also provide the name of the corresponding pokemon.\r\nI can do this by using geom_text_repel() for a subset of the labels while keeping the same geom_fit_text() setting for the rest of the labels.\r\n\r\n\r\ntm_plot_data %>% \r\n ggplot(aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1)) + \r\n geom_rect(aes(fill = color, size = primary_group),\r\n show.legend = FALSE, color = \"black\", alpha = .3) +\r\n scale_fill_identity() +\r\n scale_size(range = range(tm_plot_data$primary_group)) +\r\n ggfittext::geom_fit_text(data = filter(tm_plot_data, type_1 != \"steel\" | vSize > 1),\r\n aes(label = type_2), min.size = 1) +\r\n # pick out observations of interest and annotate with geom_text_repel\r\n ggrepel::geom_text_repel(\r\n data = filter(tm_plot_data, vSize == 1, type_1 == \"steel\") %>% \r\n inner_join(pokemon, by = c(\"type_1\", \"type_2\")),\r\n aes(x = x, y = y, label = glue::glue(\"{type_2} ({pokemon})\")),\r\n color = \"black\", xlim = c(1.02, NA), size = 4,\r\n direction = \"y\", vjust = .5, force = 3\r\n ) +\r\n # expand x-axis limits to make room for test annotations\r\n scale_x_continuous(limits = c(0, 1.2), expand = c(0, 0)) +\r\n scale_y_continuous(expand = c(0, 0)) +\r\n theme_void()\r\n\r\n\r\n\r\n\r\nAnd that’s our final product! This would’ve been pretty difficult to do with any of the three options I reviewed at the top!\r\ntl;dr - Use treemap() from the {treemap} package to get positions for geom_rect()s and you’re 90% of the way there to plotting a treemap! Apply your favorite styles (especially _text() geoms) from the {ggplot2} ecosystem for finishing touches!\r\n \r\nSession Info\r\n\r\n\r\nsessionInfo()\r\n\r\n\r\n R version 4.0.3 (2020-10-10)\r\n Platform: x86_64-w64-mingw32/x64 (64-bit)\r\n Running under: Windows 10 x64 (build 18363)\r\n \r\n Matrix products: default\r\n \r\n locale:\r\n [1] LC_COLLATE=English_United States.1252 \r\n [2] LC_CTYPE=English_United States.1252 \r\n [3] LC_MONETARY=English_United States.1252\r\n [4] LC_NUMERIC=C \r\n [5] LC_TIME=English_United States.1252 \r\n \r\n attached base packages:\r\n [1] stats graphics grDevices datasets utils methods base \r\n \r\n other attached packages:\r\n [1] treemapify_2.5.3 treemap_2.4-2 printr_0.1 forcats_0.5.0 \r\n [5] stringr_1.4.0 dplyr_1.0.2 purrr_0.3.4 readr_1.4.0 \r\n [9] tidyr_1.1.2 tibble_3.0.4 ggplot2_3.3.2 tidyverse_1.3.0 \r\n \r\n loaded via a namespace (and not attached):\r\n [1] httr_1.4.2 jsonlite_1.7.1 modelr_0.1.8 \r\n [4] shiny_1.5.0 assertthat_0.2.1 highr_0.8 \r\n [7] blob_1.2.1 renv_0.12.0 cellranger_1.1.0 \r\n [10] ggrepel_0.8.2 yaml_2.2.1 pillar_1.4.6 \r\n [13] backports_1.1.10 glue_1.4.2 digest_0.6.26 \r\n [16] RColorBrewer_1.1-2 promises_1.1.1 rvest_0.3.6 \r\n [19] colorspace_1.4-1 htmltools_0.5.0 httpuv_1.5.4 \r\n [22] pkgconfig_2.0.3 broom_0.7.2 haven_2.3.1 \r\n [25] xtable_1.8-4 scales_1.1.1 later_1.1.0.1 \r\n [28] distill_1.0.1 downlit_0.2.0 generics_0.0.2 \r\n [31] farver_2.0.3 ellipsis_0.3.1 withr_2.2.0 \r\n [34] cli_2.1.0 magrittr_1.5.0.9000 crayon_1.3.4 \r\n [37] readxl_1.3.1 mime_0.9 evaluate_0.14 \r\n [40] fs_1.5.0 fansi_0.4.1 xml2_1.3.2 \r\n [43] tools_4.0.3 data.table_1.13.2 hms_0.5.3 \r\n [46] lifecycle_0.2.0 gridBase_0.4-7 munsell_0.5.0 \r\n [49] reprex_0.3.0 compiler_4.0.3 rlang_0.4.8 \r\n [52] grid_4.0.3 gt_0.2.2 rstudioapi_0.11 \r\n [55] igraph_1.2.6 labeling_0.4.2 rmarkdown_2.5 \r\n [58] gtable_0.3.0 DBI_1.1.0 R6_2.4.1 \r\n [61] lubridate_1.7.9 knitr_1.30 fastmap_1.0.1 \r\n [64] prismatic_0.2.0 stringi_1.5.3 Rcpp_1.0.5 \r\n [67] vctrs_0.3.4 ggfittext_0.9.0 dbplyr_1.4.4 \r\n [70] tidyselect_1.1.0 xfun_0.18\r\n\r\n\r\nYou might get a warning referencing something about data.table here. No worries if this happens. The outdated {treemap} source code is built on {data.table} and contains a deprecated argument.↩︎\r\nI highly recommend checking {ggfittext} out! Here’s the github repo. Also, this is more of a note to myself but I had some trouble getting this to work at first because the min.size argument defaults to 4, meaning that all fitted text smaller than size 4 are simply not plotted (so I couldn’t get geom_fit_text() to print anything in my treemap at first). You can compare and see the threshold by looking at the geom_text_repel() texts in my second example which also has a size of 4.↩︎\r\n", + "preview": "posts/2020-06-30-treemap-with-ggplot/2020-06-30-treemap-with-ggplot_files/figure-html5/unnamed-chunk-12-1.png", + "last_modified": "2020-11-04T22:34:24-05:00", + "input_file": {}, + "preview_width": 1920, + "preview_height": 768 + }, + { + "path": "posts/2020-06-25-indexing-tip-for-spacyr/", + "title": "Indexing tip for {spacyr}", + "description": "Speeding up the analysis of dependency relations.", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-06-25", + "categories": [ + "data wrangling", + "NLP", + "spacyr" + ], + "contents": "\r\n\r\n\r\n\r\nThe {spacyr} package is an R wrapper for Python’s spaCy package, powered by {reticulate}. Although it’s been around for over 3 years, it doesn’t seem to have really been picked up by R users.1 I actually think this makes sense since what makes spaCy so great is its object-oriented approach to NLP (which Python is good at). But perhaps more importantly, a good portion of data wrangling in spaCy is reducible to operating on vectors of such tokens, and I think that comes pretty naturally for R users with a functional programming background.2 So my guess is that since spaCy is accessible to R users, {spacyr} isn’t that widely used.\r\nBut with that said, I like to make my workflow as R-centered as possible and I think there’s still value in {spacyr} at least for very simple, exploratory analysis of text. The results being returned in a tidy format is a huge plus, and it doesn’t seem to sacrifice much speed.\r\nThere’s a good guide to using {spacyr} in the CRAN vignette which covers pretty much everything you need to know if you’re already familiar with spaCy (and if you aren’t, there’s a great cheatsheet from DataCamp).\r\nEverything I just said above was just a whole lot of background information. What I really want to do here to contribute to the discussion around {spacyr} by sharing a tip for analyzing dependency relations from the output of spacy_parse(), which is {spacyr}’s main function that combines both the model-loading and text-processing stages of spaCy.\r\n\r\n\r\n\r\nFor illustration, I’ll be using the 8 State of the Union addresses by President Barack Obama from 2009-2016, which comes from the {sotu} package.\r\n\r\n\r\nlibrary(sotu)\r\ndoc <- tail(sotu::sotu_text, 8)\r\n\r\n# First 100 characters of each speech\r\nstrtrim(doc, 100)\r\n\r\n\r\n [1] \"Madam Speaker, Mr. Vice President, Members of Congress, the First Lady of the United States--she's a\"\r\n [2] \"Madam Speaker, Vice President Biden, Members of Congress, distinguished guests, and fellow Americans\"\r\n [3] \"Mr. Speaker, Mr. Vice President, Members of Congress, distinguished guests, and fellow Americans: To\"\r\n [4] \"Mr. Speaker, Mr. Vice President, Members of Congress, distinguished guests, and fellow Americans: La\"\r\n [5] \"Please, everybody, have a seat. Mr. Speaker, Mr. Vice President, Members of Congress, fellow America\"\r\n [6] \"The President. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: Today in A\"\r\n [7] \"The President. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: We are 15 \"\r\n [8] \"Thank you. Mr. Speaker, Mr. Vice President, Members of Congress, my fellow Americans: Tonight marks \"\r\n\r\nWe can pass this document to spacy_parse() to get back a dataframe of tokens and their attributes in tidy format, where each row (observation) is a token.3\r\n\r\n\r\nparsed <- spacy_parse(doc, dep = TRUE, entity = FALSE)\r\n\r\nhead(parsed, 10)\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n1\r\n\r\n\r\nMadam\r\n\r\n\r\nMadam\r\n\r\n\r\nPROPN\r\n\r\n\r\n2\r\n\r\n\r\ncompound\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n2\r\n\r\n\r\nSpeaker\r\n\r\n\r\nSpeaker\r\n\r\n\r\nPROPN\r\n\r\n\r\n2\r\n\r\n\r\nROOT\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n3\r\n\r\n\r\n,\r\n\r\n\r\n,\r\n\r\n\r\nPUNCT\r\n\r\n\r\n2\r\n\r\n\r\npunct\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n4\r\n\r\n\r\nMr. \r\n\r\n\r\nMr. \r\n\r\n\r\nPROPN\r\n\r\n\r\n6\r\n\r\n\r\ncompound\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n5\r\n\r\n\r\nVice\r\n\r\n\r\nVice\r\n\r\n\r\nPROPN\r\n\r\n\r\n6\r\n\r\n\r\ncompound\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n6\r\n\r\n\r\nPresident\r\n\r\n\r\nPresident\r\n\r\n\r\nPROPN\r\n\r\n\r\n2\r\n\r\n\r\nappos\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n7\r\n\r\n\r\n,\r\n\r\n\r\n,\r\n\r\n\r\nPUNCT\r\n\r\n\r\n6\r\n\r\n\r\npunct\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n8\r\n\r\n\r\nMembers\r\n\r\n\r\nMembers\r\n\r\n\r\nPROPN\r\n\r\n\r\n6\r\n\r\n\r\nappos\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n9\r\n\r\n\r\nof\r\n\r\n\r\nof\r\n\r\n\r\nADP\r\n\r\n\r\n8\r\n\r\n\r\nprep\r\n\r\n\r\ntext1\r\n\r\n\r\n1\r\n\r\n\r\n10\r\n\r\n\r\nCongress\r\n\r\n\r\nCongress\r\n\r\n\r\nPROPN\r\n\r\n\r\n9\r\n\r\n\r\npobj\r\n\r\n\r\nThis output format is great for plotting in R with the familiar packages. For example, we can make a bar plot of top adjectives used by Obama in his SOTU addresses with minimal changes to the output.\r\n\r\n\r\n# Load tidytext package for stopwords\r\nlibrary(tidytext)\r\n\r\nparsed %>%\r\n filter(pos == \"ADJ\",\r\n str_detect(lemma, \"^[:alpha:].*[:alpha:]$\"),\r\n !lemma %in% tidytext::stop_words$word) %>%\r\n count(lemma) %>% \r\n mutate(lemma = fct_reorder(str_to_title(lemma), n)) %>%\r\n top_n(15) %>% \r\n ggplot(aes(lemma, n)) +\r\n geom_col() +\r\n coord_flip() +\r\n labs(title = \"Top 15 Adjectives from President Obama's SOTU Addresses\",\r\n x = \"Adjective\", y = \"Count\") +\r\n theme_classic()\r\n\r\n\r\n\r\n\r\nThe Challenge\r\nBut what if we want to dig a little deeper in our analysis of adjectives? What if, for example, we were interested in the adjectives that were used to describe “America”\r\nBecause we set dep = TRUE when we called spacy_parse() earlier, we have information about dependencies in the dep_rel column and the head_token_id column. To be more precise, dep_rel is the .dep_ attribute from spaCy and head_token_id is the row index of the head token (.head attribute from spaCy) that is unique to the spacy_parse() output.\r\nFor example, let’s look at the the 298th sentence from Obama’s third SOTU address:\r\n\r\n\r\nexample_sentence <- parsed %>% \r\n filter(doc_id == \"text3\", sentence_id == 298) %>% \r\n pull(token) %>% \r\n str_c(collapse = \" \") %>% \r\n str_remove_all(\" (?=[:punct:])\")\r\n\r\nexample_sentence\r\n\r\n\r\n [1] \"Now, we've made great strides over the last 2 years in using technology and getting rid of waste.\"\r\n\r\nAnd here’s a visualization of the dependency parse made with displaCy. Sadly, displaCy is not a part of {spacyr}, so I’m just calling Python here using {reticulate}.\r\n\r\n######## Python Code ########\r\nimport spacy\r\nfrom spacy import displacy\r\nnlp = spacy.load('en_core_web_sm')\r\nexample_parsed = nlp(r.example_sentence)\r\n\r\n\r\ndisplacy.render(example_parsed, style = \"dep\")\r\n\r\n\r\n .superbigimage{\r\n overflow-x:scroll;\r\n white-space: nowrap;\r\n }\r\n .superbigimage img{\r\n max-width: none;\r\n }\r\n\r\n\r\n‘Now,ADVwePRON'veAUXmadeVERBgreatADJstridesNOUNoverADPtheDETlastADJ2NUMyearsNOUNinADPusingVERBtechnologyNOUNandCCONJgettingVERBridVERBofADPwaste.NOUNadvmodnsubjauxamoddobjprepdetamodnummodpobjpreppcompdobjccauxpassconjpreppobj’\r\n\r\n\r\n \r\nBasically, the task here is to find words like “competitive” in the example sentence above where the token is an adjective and its head is the word “America”, but it turns out harder than it seems.\r\nThe output of spacy_parse is set up such that every sentence stands on their own. More specifically speaking, the indices stored in token_id and head_token_id are local indices relative to each sentence.4 So while there are a total of 62791 tokens in parsed, the max token_id is 99, which is the index of the last token in the longest sentence.\r\nA strictly tidyverse approach (which has become a sort of a tunnel-vision for me) would be to split parsed by sentence and map a filter function to each sentence. There are two ways of going about this and both are pretty slow.\r\nThe first way is to explicitly split the dataframe into a list of dataframes at the sentence level then map the filter function, using group_split() then map_df():\r\n\r\n\r\ntic <- Sys.time()\r\n\r\nparsed %>%\r\n group_split(doc_id, sentence_id, .drop = FALSE) %>%\r\n map_df(~filter(., pos == \"ADJ\", slice(.x, head_token_id)$lemma == \"America\"))\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext3\r\n\r\n\r\n302\r\n\r\n\r\n33\r\n\r\n\r\ncompetitive\r\n\r\n\r\ncompetitive\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\namod\r\n\r\n\r\ntext4\r\n\r\n\r\n231\r\n\r\n\r\n33\r\n\r\n\r\nrural\r\n\r\n\r\nrural\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\namod\r\n\r\n\r\ntext5\r\n\r\n\r\n245\r\n\r\n\r\n2\r\n\r\n\r\nstronger\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n3\r\n\r\n\r\namod\r\n\r\n\r\ntext6\r\n\r\n\r\n340\r\n\r\n\r\n18\r\n\r\n\r\nstrong\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n21\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n23\r\n\r\n\r\nliberal\r\n\r\n\r\nliberal\r\n\r\n\r\nADJ\r\n\r\n\r\n24\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n27\r\n\r\n\r\nconservative\r\n\r\n\r\nconservative\r\n\r\n\r\nADJ\r\n\r\n\r\n28\r\n\r\n\r\namod\r\n\r\n\r\nSys.time() - tic\r\n\r\n\r\n Time difference of 12.0861 secs\r\n\r\nThe second way is to implicitly declare a grouping by sentence and then map the filter function, using group_by() then group_map():\r\n\r\n\r\ntic <- Sys.time()\r\n\r\nparsed %>%\r\n group_by(doc_id, sentence_id) %>%\r\n group_map(~filter(., pos == \"ADJ\", slice(.x, head_token_id)$lemma == \"America\"), .keep = TRUE) %>%\r\n bind_rows()\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext3\r\n\r\n\r\n302\r\n\r\n\r\n33\r\n\r\n\r\ncompetitive\r\n\r\n\r\ncompetitive\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\namod\r\n\r\n\r\ntext4\r\n\r\n\r\n231\r\n\r\n\r\n33\r\n\r\n\r\nrural\r\n\r\n\r\nrural\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\namod\r\n\r\n\r\ntext5\r\n\r\n\r\n245\r\n\r\n\r\n2\r\n\r\n\r\nstronger\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n3\r\n\r\n\r\namod\r\n\r\n\r\ntext6\r\n\r\n\r\n340\r\n\r\n\r\n18\r\n\r\n\r\nstrong\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n21\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n23\r\n\r\n\r\nliberal\r\n\r\n\r\nliberal\r\n\r\n\r\nADJ\r\n\r\n\r\n24\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n27\r\n\r\n\r\nconservative\r\n\r\n\r\nconservative\r\n\r\n\r\nADJ\r\n\r\n\r\n28\r\n\r\n\r\namod\r\n\r\n\r\nSys.time() - tic\r\n\r\n\r\n Time difference of 11.63191 secs\r\n\r\nBoth ways give us the result we want, but it’s significantly slower than what we could quickly and easily do in Python.\r\n\r\n######## Python Code ########\r\ndoc = nlp(' '.join(r.doc))\r\n\r\nimport time\r\ntic = time.time()\r\n\r\n[token.text for token in doc if token.pos_ == \"ADJ\" and token.head.lemma_ == \"America\"]\r\n ['competitive', 'rural', 'stronger', 'strong', 'liberal', 'conservative']\r\ntime.time() - tic\r\n 0.04711294174194336\r\n\r\nA Work-around\r\nWhat would really help here is if we had global indices for tokens and head tokens, so that we can directly index a head from a token without going through the trouble of figuring out how sentences are organized in the dataframe.\r\nSo here’s my take on doing this:\r\n\r\n\r\n# Calculate global indices from local indices\r\nglobal_index <- parsed %>% \r\n group_by(doc_id, sentence_id) %>% \r\n # add token counts for each sentence\r\n add_count() %>% \r\n ungroup() %>% \r\n select(doc_id, sentence_id, n) %>% \r\n distinct() %>%\r\n # take the cumulative sum and shift 1 to the right (fill first index with 0)\r\n mutate(n = c(0, cumsum(n)[1:n()-1]))\r\n\r\n# Clean the output\r\nparsed2 <- parsed %>% \r\n inner_join(global_index, by = c(\"doc_id\", \"sentence_id\")) %>% \r\n mutate(token_id_global = token_id + n,\r\n head_token_id_global = head_token_id + n) %>% \r\n relocate(token_id_global, .after = token_id) %>% \r\n relocate(head_token_id_global, .after = head_token_id) %>% \r\n select(-n)\r\n\r\n\r\n\r\nThis adds two colums - token_id_global and head_token_id_global - that stores indices that range over the entire dataframe. Here’s a sample of the new dataframe to demonstrate:\r\n\r\n\r\nsample_n(parsed2, 10)\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken_id_global\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\nhead_token_id_global\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext7\r\n\r\n\r\n37\r\n\r\n\r\n11\r\n\r\n\r\n48388\r\n\r\n\r\nto\r\n\r\n\r\nto\r\n\r\n\r\nADP\r\n\r\n\r\n10\r\n\r\n\r\n48387\r\n\r\n\r\ndative\r\n\r\n\r\ntext3\r\n\r\n\r\n154\r\n\r\n\r\n3\r\n\r\n\r\n18253\r\n\r\n\r\nthe\r\n\r\n\r\nthe\r\n\r\n\r\nDET\r\n\r\n\r\n5\r\n\r\n\r\n18255\r\n\r\n\r\ndet\r\n\r\n\r\ntext1\r\n\r\n\r\n44\r\n\r\n\r\n2\r\n\r\n\r\n1036\r\n\r\n\r\nof\r\n\r\n\r\nof\r\n\r\n\r\nADP\r\n\r\n\r\n1\r\n\r\n\r\n1035\r\n\r\n\r\npcomp\r\n\r\n\r\ntext8\r\n\r\n\r\n17\r\n\r\n\r\n6\r\n\r\n\r\n56007\r\n\r\n\r\nto\r\n\r\n\r\nto\r\n\r\n\r\nADP\r\n\r\n\r\n5\r\n\r\n\r\n56006\r\n\r\n\r\nprep\r\n\r\n\r\ntext5\r\n\r\n\r\n316\r\n\r\n\r\n3\r\n\r\n\r\n38631\r\n\r\n\r\nthis\r\n\r\n\r\nthis\r\n\r\n\r\nDET\r\n\r\n\r\n4\r\n\r\n\r\n38632\r\n\r\n\r\nnsubj\r\n\r\n\r\ntext6\r\n\r\n\r\n340\r\n\r\n\r\n15\r\n\r\n\r\n46579\r\n\r\n\r\nthen\r\n\r\n\r\nthen\r\n\r\n\r\nADV\r\n\r\n\r\n23\r\n\r\n\r\n46587\r\n\r\n\r\nadvmod\r\n\r\n\r\ntext4\r\n\r\n\r\n162\r\n\r\n\r\n7\r\n\r\n\r\n26488\r\n\r\n\r\n\r\n\r\n\r\n\r\nSPACE\r\n\r\n\r\n6\r\n\r\n\r\n26487\r\n\r\n\r\n\r\n\r\ntext6\r\n\r\n\r\n87\r\n\r\n\r\n13\r\n\r\n\r\n41466\r\n\r\n\r\nto\r\n\r\n\r\nto\r\n\r\n\r\nPART\r\n\r\n\r\n14\r\n\r\n\r\n41467\r\n\r\n\r\naux\r\n\r\n\r\ntext8\r\n\r\n\r\n260\r\n\r\n\r\n17\r\n\r\n\r\n60517\r\n\r\n\r\npositioned\r\n\r\n\r\nposition\r\n\r\n\r\nVERB\r\n\r\n\r\n9\r\n\r\n\r\n60509\r\n\r\n\r\nconj\r\n\r\n\r\ntext8\r\n\r\n\r\n281\r\n\r\n\r\n2\r\n\r\n\r\n60856\r\n\r\n\r\nis\r\n\r\n\r\nbe\r\n\r\n\r\nAUX\r\n\r\n\r\n11\r\n\r\n\r\n60865\r\n\r\n\r\nccomp\r\n\r\n\r\nAnd since this process isn’t destructive, we actually don’t need to assign the output to a new object. This is great because we can flexibly incorporate it into the pipeline workflow.\r\nHere is my solution wrapped in a function:5\r\n\r\n\r\nadd_global_index <- function(spacy_parsed) {\r\n \r\n global_index <- spacy_parsed %>% \r\n group_by(doc_id, sentence_id) %>% \r\n add_count() %>% \r\n ungroup() %>% \r\n select(doc_id, sentence_id, n) %>% \r\n distinct() %>%\r\n mutate(n = c(0, cumsum(n)[1:n()-1]))\r\n \r\n spacy_parsed %>% \r\n inner_join(global_index, by = c(\"doc_id\", \"sentence_id\")) %>% \r\n mutate(token_id_global = token_id + n,\r\n head_token_id_global = head_token_id + n) %>% \r\n relocate(token_id_global, .after = token_id) %>% \r\n relocate(head_token_id_global, .after = head_token_id) %>% \r\n select(-n)\r\n \r\n}\r\n\r\n\r\n\r\nIn action:\r\n\r\n\r\n# Find adjectives describing \"America\"\r\nparsed %>% \r\n add_global_index() %>% \r\n filter(pos == \"ADJ\", slice(., head_token_id_global)$lemma == \"America\")\r\n\r\n\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken_id_global\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\nhead_token_id_global\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext3\r\n\r\n\r\n302\r\n\r\n\r\n33\r\n\r\n\r\n21359\r\n\r\n\r\ncompetitive\r\n\r\n\r\ncompetitive\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\n21360\r\n\r\n\r\namod\r\n\r\n\r\ntext4\r\n\r\n\r\n231\r\n\r\n\r\n33\r\n\r\n\r\n27772\r\n\r\n\r\nrural\r\n\r\n\r\nrural\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\n27773\r\n\r\n\r\namod\r\n\r\n\r\ntext5\r\n\r\n\r\n245\r\n\r\n\r\n2\r\n\r\n\r\n36825\r\n\r\n\r\nstronger\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n3\r\n\r\n\r\n36826\r\n\r\n\r\namod\r\n\r\n\r\ntext6\r\n\r\n\r\n340\r\n\r\n\r\n18\r\n\r\n\r\n46582\r\n\r\n\r\nstrong\r\n\r\n\r\nstrong\r\n\r\n\r\nADJ\r\n\r\n\r\n21\r\n\r\n\r\n46585\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n23\r\n\r\n\r\n54054\r\n\r\n\r\nliberal\r\n\r\n\r\nliberal\r\n\r\n\r\nADJ\r\n\r\n\r\n24\r\n\r\n\r\n54055\r\n\r\n\r\namod\r\n\r\n\r\ntext7\r\n\r\n\r\n317\r\n\r\n\r\n27\r\n\r\n\r\n54058\r\n\r\n\r\nconservative\r\n\r\n\r\nconservative\r\n\r\n\r\nADJ\r\n\r\n\r\n28\r\n\r\n\r\n54059\r\n\r\n\r\namod\r\n\r\n\r\n\r\n\r\n# Find adjectives describing \"America\" inside a prepositional phrase\r\nparsed %>% \r\n add_global_index() %>% \r\n filter(pos == \"ADJ\", slice(., head_token_id_global)$lemma == \"America\",\r\n slice(., slice(., head_token_id_global)$head_token_id_global)$dep_rel == \"prep\")\r\n\r\n\r\n\r\n\r\n\r\ndoc_id\r\n\r\n\r\nsentence_id\r\n\r\n\r\ntoken_id\r\n\r\n\r\ntoken_id_global\r\n\r\n\r\ntoken\r\n\r\n\r\nlemma\r\n\r\n\r\npos\r\n\r\n\r\nhead_token_id\r\n\r\n\r\nhead_token_id_global\r\n\r\n\r\ndep_rel\r\n\r\n\r\ntext3\r\n\r\n\r\n302\r\n\r\n\r\n33\r\n\r\n\r\n21359\r\n\r\n\r\ncompetitive\r\n\r\n\r\ncompetitive\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\n21360\r\n\r\n\r\namod\r\n\r\n\r\ntext4\r\n\r\n\r\n231\r\n\r\n\r\n33\r\n\r\n\r\n27772\r\n\r\n\r\nrural\r\n\r\n\r\nrural\r\n\r\n\r\nADJ\r\n\r\n\r\n34\r\n\r\n\r\n27773\r\n\r\n\r\namod\r\n\r\n\r\nPerformance:\r\n\r\n\r\ntest <- function(){\r\n parsed %>% \r\n add_global_index() %>% \r\n filter(pos == \"ADJ\", slice(., head_token_id_global)$lemma == \"America\")\r\n}\r\n\r\nprint(microbenchmark::microbenchmark(test(), unit = \"s\"))\r\n\r\n\r\n Unit: seconds\r\n expr min lq mean median uq max neval\r\n test() 0.0909179 0.09831835 0.1109029 0.10356 0.1122529 0.3129214 100\r\n\r\nMuch better!\r\n \r\nSession Info\r\n\r\n R version 4.0.3 (2020-10-10)\r\n Platform: x86_64-w64-mingw32/x64 (64-bit)\r\n Running under: Windows 10 x64 (build 18363)\r\n \r\n Matrix products: default\r\n \r\n locale:\r\n [1] LC_COLLATE=English_United States.1252 \r\n [2] LC_CTYPE=English_United States.1252 \r\n [3] LC_MONETARY=English_United States.1252\r\n [4] LC_NUMERIC=C \r\n [5] LC_TIME=English_United States.1252 \r\n \r\n attached base packages:\r\n [1] stats graphics grDevices datasets utils methods base \r\n \r\n other attached packages:\r\n [1] tidytext_0.2.6 sotu_1.0.2 reticulate_1.18 stringr_1.4.0 \r\n [5] spacyr_1.2.1 forcats_0.5.0 ggplot2_3.3.2 purrr_0.3.4 \r\n [9] dplyr_1.0.2 printr_0.1 \r\n \r\n loaded via a namespace (and not attached):\r\n [1] Rcpp_1.0.5 highr_0.8 pillar_1.4.6 \r\n [4] compiler_4.0.3 tokenizers_0.2.1 tools_4.0.3 \r\n [7] digest_0.6.26 downlit_0.2.0 jsonlite_1.7.1 \r\n [10] lattice_0.20-41 evaluate_0.14 lifecycle_0.2.0 \r\n [13] tibble_3.0.4 gtable_0.3.0 pkgconfig_2.0.3 \r\n [16] rlang_0.4.8 Matrix_1.2-18 rstudioapi_0.11 \r\n [19] microbenchmark_1.4-7 distill_1.0 yaml_2.2.1 \r\n [22] xfun_0.18 janeaustenr_0.1.5 withr_2.2.0 \r\n [25] knitr_1.30 rappdirs_0.3.1 generics_0.0.2 \r\n [28] vctrs_0.3.4 grid_4.0.3 tidyselect_1.1.0 \r\n [31] data.table_1.13.2 glue_1.4.2 R6_2.4.1 \r\n [34] fansi_0.4.1 rmarkdown_2.5 farver_2.0.3 \r\n [37] magrittr_1.5.0.9000 SnowballC_0.7.0 prismatic_0.2.0 \r\n [40] scales_1.1.1 ellipsis_0.3.1 htmltools_0.5.0 \r\n [43] gt_0.2.2 colorspace_1.4-1 renv_0.12.0 \r\n [46] labeling_0.4.2 stringi_1.5.3 munsell_0.5.0 \r\n [49] crayon_1.3.4\r\n\r\n\r\nThere are less than 30 posts about it on StackOverflow, for example.↩︎\r\nI personally found it very easy to pick up vector comprehension in Python after working with purrr::map, for example.↩︎\r\nThe argument entity = FALSE is the same as disable = ['ner'] in spacy.load() in Python. I did this to save computation time.↩︎\r\nThis format is shared across other NLP packages in R based on spacCy, like {cleanNLP}↩︎\r\nThis would need to be tweaked a bit if you want to use it for the output of {cleanNLP} because the column for the local index of token heads, tid_source, is 0 when the token is the ROOT, as opposed to its own token index, which is the case in {spacyr}. You could add something like mutate(tid_source = ifelse(tid_source == 0, tid, tid_source) to the beginning of the pipeline to address this.↩︎\r\n", + "preview": "posts/2020-06-25-indexing-tip-for-spacyr/preview.png", + "last_modified": "2020-11-01T19:52:47-05:00", + "input_file": {}, + "preview_width": 1920, + "preview_height": 686 + }, + { + "path": "posts/2020-06-07-correlation-parameter-mem/", + "title": "The Correlation Parameter in Mixed Effects Models", + "description": "Notes on the Corr term in {lme4} output", + "author": [ + { + "name": "June Choe", + "url": {} + } + ], + "date": "2020-06-07", + "categories": [ + "statistics", + "mixed-effects models", + "tutorial" + ], + "contents": "\r\n\r\n\r\n\r\nWhat is Corr in the output of mixed-effects models?\r\nWhen fitting mixed effects regression models, especially those that try to keep it “maximal” (as per Barr, Levy, Scheepers, & Tily 2013), the random effects in the output of the model sometimes displays a column named Corr where some rows have numbers that range from -1 to 1.\r\n\r\nIt’s easy to guess that Corr stands for correlation and that the numbers in the column are correlation coefficients. If there are multiple predictors and the random effects structure includes more than one of those terms (e.g., (1 + Effect_1 * Effect_2 | Subject)), we even get another clue for this from the way that the Corr values spread out in the shape of a right triangle, much like in a correlation matrix.\r\n\r\nDespite the fact that we’re bound to have encountered this at some point when working with or reading about mixed effects models, I’ve found that there aren’t many beginner-friendly material explaining what they are - there are one-paragraph StackExchange answers and dense statistics papers, but not much in between in terms of comprehensiveness.\r\nSo here are my compiled notes on correlation parameters in linear mixed effects models that I’ve made for myself (with a basic knowledge of LMEMs).\r\nBefore we get started\r\nOur toy data and model\r\n\r\n\r\n\r\nFor the purposes of this discussion, I have created a toy experiment data (the code used to generate it is attached at the bottom).\r\nThe dataset toydata has 1,920 rows with the following columns:\r\nSubject: The subject ID, which ranges from 1 to 80\r\nItem: The item ID, which ranges from 1 to 24\r\nCondition: The experimental condition, which is either Control or Treatment\r\nResponse: A continuous observed variable\r\n\r\n\r\n\r\n\r\n\r\ntoydata\r\n\r\n\r\n # A tibble: 1,920 x 4\r\n Subject Item Condition Response\r\n \r\n 1 1 1 Control 226.\r\n 2 1 2 Treatment 300.\r\n 3 1 3 Control 239.\r\n 4 1 4 Treatment 262.\r\n 5 1 5 Control 241.\r\n 6 1 6 Treatment 264.\r\n 7 1 7 Control 237.\r\n 8 1 8 Treatment 230.\r\n 9 1 9 Control 229.\r\n 10 1 10 Treatment 283.\r\n # ... with 1,910 more rows\r\n\r\nImagine toydata to be the results from a very simple experiment. In this imaginary experiment, there are 80 subjects and each subject is tested on 24 items, resulting in a total of 1,920 trials/observations. This is a within-partipant design, so each participant sees 12 of the items in the Control condition and the other 12 in the Treatment condition.\r\nLet’s say that with our toy data, we want to know whether Condition has a positive effect on Response. Our goal by using mixed-effects modeling is to isolate the effect of Condition on Response (fixed effect), while controlling for by-item and by-subject variations (random effects). So let’s fit a simple linear mixed-effects model with the maximal random effects structure, with random intercepts and slopes for Condition by Subject and Item:\r\n\r\n\r\nmodel <- lmer(Response ~ Condition + (1+Condition|Subject) + (1+Condition|Item),\r\n REML = FALSE, control = lmerControl('bobyqa'), data = toydata)\r\n\r\n\r\n\r\nAnd let’s really quickly check model assumptions:\r\n\r\n\r\nperformance::check_model(model)\r\n\r\n\r\n\r\n\r\nEverything looks okay, so let’s look at the model output:\r\n\r\n\r\nsummary(model)\r\n\r\n\r\n Linear mixed model fit by maximum likelihood . t-tests use Satterthwaite's\r\n method [lmerModLmerTest]\r\n Formula: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition | \r\n Item)\r\n Data: toydata\r\n Control: lmerControl(\"bobyqa\")\r\n \r\n AIC BIC logLik deviance df.resid \r\n 13267 13317 -6624 13249 1911 \r\n \r\n Scaled residuals: \r\n Min 1Q Median 3Q Max \r\n -3.176 -0.627 -0.065 0.576 4.864 \r\n \r\n Random effects:\r\n Groups Name Variance Std.Dev. Corr\r\n Subject (Intercept) 637.1 25.24 \r\n ConditionTreatment 108.1 10.40 0.85\r\n Item (Intercept) 44.4 6.66 \r\n ConditionTreatment 308.2 17.56 0.14\r\n Residual 37.4 6.11 \r\n Number of obs: 1920, groups: Subject, 80; Item, 24\r\n \r\n Fixed effects:\r\n Estimate Std. Error df t value Pr(>|t|) \r\n (Intercept) 209.64 3.14 100.84 66.8 < 2e-16 ***\r\n ConditionTreatment 35.88 3.78 28.52 9.5 2.5e-10 ***\r\n ---\r\n Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\r\n \r\n Correlation of Fixed Effects:\r\n (Intr)\r\n CndtnTrtmnt 0.291\r\n\r\nThe high t-statistic and low p-value of ConditionTreatment in the fixed effects output suggests that our data is extremely unlikely given the null hypothesis that Condition has no effect on Response (and the sign of the estimate further suggests a positive effect of the Treatment condition on Response compared to the Control condition). Therefore, this is strong evidence in support of our hypothesis.\r\nHere’s a nicer-looking summary table made with tab_model() from the {sjPlot} package. I will keep using this format from this point on. Not only is this nicer to look at, the notations used here (like \\(\\tau_{00}\\) and \\(\\rho_{01}\\)) are from Barr et al. (2013), so it’s easier to connect the pieces IMO.\r\n\r\n\r\nsjPlot::tab_model(model)\r\n\r\n\r\n\r\n \r\n\r\n\r\nResponse\r\n\r\n\r\nPredictors\r\n\r\n\r\nEstimates\r\n\r\n\r\nCI\r\n\r\n\r\np\r\n\r\n\r\n(Intercept)\r\n\r\n\r\n209.64\r\n\r\n\r\n203.49 – 215.80\r\n\r\n\r\n<0.001\r\n\r\n\r\nCondition [Treatment]\r\n\r\n\r\n35.88\r\n\r\n\r\n28.48 – 43.28\r\n\r\n\r\n<0.001\r\n\r\n\r\nRandom Effects\r\n\r\n\r\nσ2\r\n\r\n37.37\r\n\r\n\r\nτ00Subject\r\n\r\n637.14\r\n\r\n\r\nτ00Item\r\n\r\n44.39\r\n\r\n\r\nτ11Subject.ConditionTreatment\r\n\r\n108.10\r\n\r\n\r\nτ11Item.ConditionTreatment\r\n\r\n308.21\r\n\r\n\r\nρ01Subject\r\n\r\n0.85\r\n\r\n\r\nρ01Item\r\n\r\n0.14\r\n\r\n\r\nICC\r\n\r\n\r\n0.97\r\n\r\n\r\nN Subject\r\n\r\n80\r\n\r\n\r\nN Item\r\n\r\n24\r\n\r\n\r\nObservations\r\n\r\n\r\n1920\r\n\r\n\r\nMarginal R2 / Conditional R2\r\n\r\n0.216 / 0.975\r\n\r\n\r\nOkay so our finding is great and all but we’re more interested in the random effects here so let’s look at that.\r\nThe random effects (a review)\r\nWe can isolate the random effects from the model using VarCorr():\r\n\r\n\r\nVarCorr(model)\r\n\r\n\r\n Groups Name Std.Dev. Corr\r\n Subject (Intercept) 25.24 \r\n ConditionTreatment 10.40 0.85\r\n Item (Intercept) 6.66 \r\n ConditionTreatment 17.56 0.14\r\n Residual 6.11\r\n\r\nLet’s ignore the Corr column for a moment and talk about Std.Dev first.\r\nThe Std.Dev. values for the Subject random effects group suggest that the variation in the subject intercepts are fitted with a larger standard deviation of 25.24 and that the variation in subject slopes for Condition are fitted with a smaller standard deviation of 10.4.\r\nLet’s plot the by-subject variation:\r\n\r\n\r\n\r\nWe see a clear variation in the intercepts, and a subtler variation in the slopes. This is overall pretty consistent with the stand deviation values for subject random effects that we found earlier.\r\nLet’s plot the by-item variation as well:\r\n\r\n\r\n\r\nHere, we see the opposite: a clear variation in the slopes, and a subtler variation in the intercepts. Again, this is overall pretty consistent given the item random effects output: a larger standard deviation for the item slopes and a smaller standard deviation for item intercepts, as we found earlier.\r\nNow that we’ve reviewed Std.Dev., let’s talk about Corr, which is our main focus.\r\nThe Correlation Parameter\r\nLooking at the Corr column now, we see two numbers: 0.85 within the Subject random effects group and 0.14 within the Item random effects group.\r\n\r\n Groups Name Std.Dev. Corr\r\n Subject (Intercept) 25.24 \r\n ConditionTreatment 10.40 0.85\r\n Item (Intercept) 6.66 \r\n ConditionTreatment 17.56 0.14\r\n Residual 6.11\r\n\r\nAs you might have guessed, they have something to do with the correlation between random effects (intercept and slope) within each group (subject and item).\r\nBut if we extract the subject random effects, for example, and measure the correlation between subject intercepts and subject slopes, we get a slightly different number:\r\n\r\n\r\n# Extract by-subject intercept and slope\r\nranef_subj <- ranef(model)$Subject\r\n\r\nranef_subj_intercepts <- ranef_subj$`(Intercept)`\r\nranef_subj_slopes <- ranef_subj$ConditionTreatment\r\n\r\n# Calculate correlation\r\ncor(ranef_subj_intercepts, ranef_subj_slopes)\r\n\r\n\r\n [1] 0.88\r\n\r\nIn fact, we get slightly different values for the standard deviation of the subject random intercepts and slopes as well:\r\n\r\n\r\n# Calculate the standard deviation of by-subject intercepts and slopes\r\nsummarize_all(ranef_subj, sd)\r\n\r\n\r\n (Intercept) ConditionTreatment\r\n 1 25.3 10.18\r\n\r\nSo it looks like what the model isn’t just taking the random effects in our toydata dataset and calculating their variations and correlations. So then what is it doing?\r\nHow the model estimates random effects\r\nWhat we have to keep in mind when doing mixed effects modeling is that the model is fitting the random effects in the data, rather than just describing them. More specifically, the model is estimating population parameters that generated the sample of random effects that are seen in the data.1\r\nAnd in fact that’s exactly what we want to do. We don’t care about how individual subjects or items behave in our experiment, in the sense that we don’t care how fast John Doe presses a button, for example. We don’t want to predict John Doe’s behavior, but we do want to estimate, using data from John Doe, Jane Doe, Average Joe, and other participants from our experiment, the overall distribution of people’s idiosyncratic tendencies so that we can statistically control for them to get a better estimate for the fixed effects that we care about.\r\nTake the random intercepts by subject for example. The model estimated the distribution of subject intercepts to follow a normal distribution with a standard deviation of 25.24, which is a an estimate of the Population. The variation in subject intercepts in the data itself that we manually calculated above (25.3) is the Sample standard deviation. Of course, if the sample follows a normal distribution and if we also assume the population to be normally distributed, the sample variance should be the best estimate for the population variance. And in fact they do end up being very close!\r\nSo the numbers in the Std.Dev. colum are the model’s fit for the variation within each random effect.\r\nWith this, we now have a better understanding of the numbers in the Corr column: they are the model’s fit for the correlation between random effects.\r\nTo go more in depth with our discussion, let’s plot the intercepts and slopes for our 80 subjects:\r\n\r\n\r\n\r\nRecall that when we manually calculated the correlation between subject intercepts and subject slopes within our sample of 80 subjects in the data, we got 0.88. That is in fact what is shown by the plot above.\r\nAnd as we discussed earlier, the numbers in the Std.Dev. column are the model’s fit for the variation within each random effect. So the model is saying that the variation for subject intercepts follows a normal distribution with mean = 0 and standard deviation = 25.24. Likewise, the model is saying that the variation for subject slopes follows a normal distribution with mean = 0 and standard deviation = 10.4.2\r\nSo the model estimates these two distributions - one for subject slopes and one for subject intercepts - to capture the overall distribution of subject random effects.\r\nThis is illustrated below, where the normal curve at the top is the distribution of subject intercepts estimated by the model, and the normal curve to the right is the distribution of subject slopes estimated by the model. For every subject, their intercepts and slopes are understood to be generated from these two underlying parameters:\r\n\r\n\r\n\r\nBut is specifying each distribution for intercept and item enough to capture the overall distribution of subject random effects?\r\nOne way to test this is to work backwards and generate some observations from the model’s parameters. The idea here is this: if the two normal distributions (one for subject intercept and one for subject slope) can sufficiently capture the distribution of the subject random effects, then sampling from them should yield a distribution that is in the shape of the actual distribution in our data.\r\nLet’s draw 80 samples of subject intercepts and subject slopes from their respective distributions and then plot them together. Here’s one result:\r\n\r\n\r\n\r\nThese points are consistent with what the two distributions predict: there are more points towards the center (the means of the distributions) and less points towards the corners (the tails of the distributions).\r\nBut this doesn’t look like the actual distribution of our subject random effects.\r\nWe can repeat this sampling procedure many times, but none of them look close to the distribution of the subject random effects in our data:\r\nFor clearer comparison, here is the plot of the subject random effects in our data again.\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\nSo what are we missing here?\r\nWell, what’s missing here is the correlation between the intercepts and slopes that I conveniently left out to demonstrate that just specifying the individual distributions for subject intercepts and subject slopes poorly captures the actual distribution of subject random effects in our data.\r\nIn more technical terms, treating the two random effects as independently sampled from their respective distributions fails to fit the data well because the two random effects are highly correlated. They should instead be treated as being jointly sampled from a bivariate distribution\r\nAnd that’s exactly what adding the correlation parameter does. Let’s break this down.\r\nWhen we say that two variables are independently sampled from two distributions (as we just did above), then their joint distribution looks something like this, where most of the data is expected to fall within the grey shaded ellipse:\r\n\r\n\r\n\r\nThis is clearly a bad fit for the distribution of our subject random effects…\r\n\r\n\r\n\r\n… because the distribution of the subject random effects actually takes the shape of a tilted ellipse instead (dotted outline):\r\n\r\n\r\n\r\nIn fact, we cannot generate any distribution of a tilted shape with just two independent distributions for each variable. We need to factor in covariation to capture the correlation between variables. Barr et al. (2013) illustrates this clearly in the supplementary materials to their paper. You can see from the plot below (originally Figure 1 on the linked page) that without the correlation parameter, you can only capture distributions that are symmetrical with respect to the axes (the darker ellipses). However, once you add in a correlation parameter (\\(\\rho\\)), you can capture distributions that are in the “tilted” shape (the lighter ellipses) like the distribution of our highly correlated subject intercepts and subject slopes.\r\n\r\n\r\n\r\nFigure 1: Figure from Barr et al. (2013)\r\n\r\n\r\n\r\nPutting it all together\r\nHere’s the output of model again:\r\n\r\n\r\n \r\n\r\n\r\nResponse\r\n\r\n\r\nPredictors\r\n\r\n\r\nEstimates\r\n\r\n\r\nCI\r\n\r\n\r\np\r\n\r\n\r\n(Intercept)\r\n\r\n\r\n209.64\r\n\r\n\r\n203.49 – 215.80\r\n\r\n\r\n<0.001\r\n\r\n\r\nCondition [Treatment]\r\n\r\n\r\n35.88\r\n\r\n\r\n28.48 – 43.28\r\n\r\n\r\n<0.001\r\n\r\n\r\nRandom Effects\r\n\r\n\r\nσ2\r\n\r\n37.37\r\n\r\n\r\nτ00Subject\r\n\r\n637.14\r\n\r\n\r\nτ00Item\r\n\r\n44.39\r\n\r\n\r\nτ11Subject.ConditionTreatment\r\n\r\n108.10\r\n\r\n\r\nτ11Item.ConditionTreatment\r\n\r\n308.21\r\n\r\n\r\nρ01Subject\r\n\r\n0.85\r\n\r\n\r\nρ01Item\r\n\r\n0.14\r\n\r\n\r\nICC\r\n\r\n\r\n0.97\r\n\r\n\r\nN Subject\r\n\r\n80\r\n\r\n\r\nN Item\r\n\r\n24\r\n\r\n\r\nObservations\r\n\r\n\r\n1920\r\n\r\n\r\nMarginal R2 / Conditional R2\r\n\r\n0.216 / 0.975\r\n\r\n\r\nAnd let’s keep focusing on the subject random effects for now.\r\nThere are three parameters that the model estimated to capture the by-subject variation:\r\nThe variation (Std.Dev.) for subject intercept\r\nThe variation (Std.Dev.) for subject slope\r\nThe correlation (Corr) between subject intercept and subject slope.\r\nWith these three parameters, the model is defining a bivariate normal distribution, from which subject intercepts (\\(S_{0s}\\)) and subject slopes (\\(S_{1s}\\)) are sampled from (Equation 3 from Barr et al., 2013):\r\n\\[(S_{0s}, S_{1s})\\ \\sim\\ N(0,\\begin{bmatrix}\\tau_{00}^2 & \\rho\\ \\tau_{00}^2 \\tau_{11}^2 \\\\ \\rho\\ \\tau_{00}^2 \\tau_{11}^2 & \\tau_{11}^2 \\end{bmatrix})\\]\r\nFor the variance-covariance matrix, we can substitute the standard deviation for the subject intercept \\(\\tau_{00}^2\\) with 25.24, the standard deviation for the subject slope \\(\\tau_{11}\\) with 10.4, and the correlation \\(\\rho\\) with 0.85 to get the following:\r\n\\[(S_{0s}, S_{1s})\\ \\sim\\ N(0,\\begin{bmatrix}25.24^2 & 0.85\\ \\times\\ 25.24\\ \\times\\ 10.4 \\\\ 0.85\\ \\times\\ 25.24\\ \\times\\ 10.4 & 10.4^2 \\end{bmatrix})\\]\r\nIf subject intercepts and subject slopes are jointly sampled from the above distribution, most observations should fall within this grey area:\r\n\r\n\r\n\r\n\r\nNotice how I added \\(\\rho = 0.85\\) in this top right corner of this plot.\r\nLet’s again repeatedly sample from this new bivariate distribution (which you can do with mvrnorm() from the {MASS} package) to check:\r\n\r\n\r\n\r\nLike we expected, this new distribution generates observations of subject slopes and subject intercepts that are highly correlated. But more importantly, the distribution of subject random effects in our data looks like it could be one of these samples, meaning that this bivariate normal distribution fits our data well.\r\nGood thing that we had the model estimate this parameter by specifying the random effects structure for subjects as (1 + Condition | Subject) in our model formula!\r\nWhat if we leave out this correlation parameter? Would it significantly worsen model fit?\r\nWe can check by building another model without the correlation term between the subject random effects and comparing it with our original model.3\r\nThe no_subj_cor_model below is a depleted model without the correlation parameter between the random intercepts and random slopes by subject. You can see that the subject group is missing a value in the Corr column.4\r\n\r\n\r\nno_subj_cor_model <- lmer(Response ~ Condition + (1+model.matrix(model)[,2]||Subject) + (1+Condition|Item),\r\n REML = FALSE, control = lmerControl('bobyqa'), data = toydata)\r\n\r\ntab_model(no_subj_cor_model)\r\n\r\n\r\n\r\n \r\n\r\n\r\nResponse\r\n\r\n\r\nPredictors\r\n\r\n\r\nEstimates\r\n\r\n\r\nCI\r\n\r\n\r\np\r\n\r\n\r\n(Intercept)\r\n\r\n\r\n209.64\r\n\r\n\r\n203.44 – 215.84\r\n\r\n\r\n<0.001\r\n\r\n\r\nCondition [Treatment]\r\n\r\n\r\n35.88\r\n\r\n\r\n28.43 – 43.33\r\n\r\n\r\n<0.001\r\n\r\n\r\nRandom Effects\r\n\r\n\r\nσ2\r\n\r\n37.34\r\n\r\n\r\nτ00Subject\r\n\r\n649.20\r\n\r\n\r\nτ00Subject.1\r\n\r\n110.96\r\n\r\n\r\nτ00Item\r\n\r\n44.56\r\n\r\n\r\nτ11Item.ConditionTreatment\r\n\r\n311.76\r\n\r\n\r\nρ01Item\r\n\r\n0.14\r\n\r\n\r\nICC\r\n\r\n\r\n0.96\r\n\r\n\r\nN Subject\r\n\r\n80\r\n\r\n\r\nN Item\r\n\r\n24\r\n\r\n\r\nObservations\r\n\r\n\r\n1920\r\n\r\n\r\nMarginal R2 / Conditional R2\r\n\r\n0.263 / 0.970\r\n\r\n\r\nNow let’s perform a likelihood ratio test using anova():\r\n\r\n\r\nanova(no_subj_cor_model, model, test = 'Chisq')\r\n\r\n\r\n Data: toydata\r\n Models:\r\n no_subj_cor_model: Response ~ Condition + (1 + model.matrix(model)[, 2] || Subject) + \r\n no_subj_cor_model: (1 + Condition | Item)\r\n model: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition | \r\n model: Item)\r\n npar AIC BIC logLik deviance Chisq Df Pr(>Chisq) \r\n no_subj_cor_model 8 13352 13396 -6668 13336 \r\n model 9 13267 13317 -6624 13249 87.2 1 <2e-16 ***\r\n ---\r\n Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\r\n\r\nThe first thing to notice is that no_subj_cor_model has one less Df, or degrees of freedom, than model. This is because every correlation between random effects is an additional parameter that the model is estimating. So removing the correlation between random effects for no_subj_cor_model leaves it with 8 parameters, one less than the original, full model. There’s a good discussion of what parameters are specified by different lmer() formulas in this StackExchange thread.\r\nAfter performing this sanity check, the next thing to note is the very low number in Pr(>Chisq), telling us that the models are significantly different from one another. This might come off as weird if you’re only used to performing ANOVA comparisons to check whether a predictor is significant or not. In fact, there are no obvious differences between the output of no_subj_cor_model and the output of our original model other than the presence/absence of the correlation between subject random effects.\r\nBut clearly something major is going on behind the curtains, so we turn to the last term(s) of interest - AIC and BIC, which are scores for model fit. The numbers are hard to interpret on their own, but useful when comparing models. Here, both the AIC and the BIC of no_subj_cor_model are higher than model, suggesting that no_subj_cor_model has a worse fit, and a statistically significant one at that.\r\nMore specifically, we know that the only meaningful difference between no_subj_cor_model and model is the correlation parameter for the subject random effects, so no_subj_cor_model must be capturing the subject random effects relativelty poorly under its assumption that subject intercepts and subject slopes do not correlate with one another (i.e., that they are independent).\r\nSo let’s look at the random effects calculated by no_subj_cor_model and its poor attempt at fitting their distribution.\r\nFirst, let’s plot the subject intercepts by subject slopes like we did for our original model:\r\n\r\n\r\n\r\nYou might notice that the no_subj_cor_model calculates subject random effects that are very similar to those calculated by our original mode. Here’s a side-by-side comparison of the subject random effects from model and no_subj_cor_model:\r\n\r\n\r\n\r\nThis illustrates a very important point. Removing the correlation parameter does not change the calculation of the random effects (barring any serious convergence failures, of course). This shouldn’t be surprising because random effects, like fixed effects, speak to facts (in the frequentist sense) about how the data that we observe is generated. It is literally the case here since I included these random effects explicitly in making toydata. But more importantly, the idea that there are random variations generated from underlying population-level parameters is an assumption that we are making when we use mixed-effects models.\r\nThe only meaningful difference between the two models here, then, is in their fit - e.g., how well the model captures the distribution of the subject random effects. We actually went over this above - we saw that our original model fits subject random effects using a bivariate normal distribution assuming a correlation, while no_subj_cor_model should be fitting subject random effects using two univariate normal distributions, assuming no (i.e., zero) correlation.\r\nHere’s a visual comparison of model fit, with the plot for model at the top and the plot for no_subj_cor_model at the bottom:\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nWhere the term \\(\\rho = 0\\) in the plot for no_subj_cor_model indicates that the subject intercepts and subject slopes are generated from this bivariate distribution:\r\n\\[(S_{0s}, S_{1s})\\ \\sim\\ N(0,\\begin{bmatrix} \\tau_{00}^2 & 0 \\\\ 0 & \\tau_{11}^2 \\end{bmatrix})\\]\r\nWhich is the same as independetly sampling from these two univariate normal distributions:\r\n\\[S_{0s} \\sim N(0, \\tau_{00})\\]\r\n\\[S_{1s} \\sim N(0, \\tau_{11})\\]\r\nNow, looking at the previous pair of plots, no_subj_cor_model (bottom) clearly fits the distribution of the subject random effects poorly compared to our original model model (top), and that appears to be the driving the significant decrease in fit that we found from the likelihood ratio test earlier. It seems to be the case that the inclusion of the correlation parameter between subject random intercepts is necessary to fit the data well.\r\nAre correlation parameters always necessary?\r\nThe question of how “maximal” our models should be is very tricky, and especially so when it concerns the inclusion/exclusion of correlation parameters (see discussions here and here). For example, Bates, Kliegl, Vasishth, & Baayen (2015) and Matuschek, Kliegl, Vasishth, & Baayen (2017) have called for parsimonious models with stricter criteria for including terms in the model, beyond whether they cause the model to fail to converge.5\r\nI’ll demonstrate one case here where it doesn’t seem like including a correlation parameter particularly improves model fit.\r\nLet’s repeat the model comparison process above, except this time taking out the correlation parameter for item.\r\nFor context, here is the random effects output of model again:\r\n\r\n Groups Name Std.Dev. Corr\r\n Subject (Intercept) 25.24 \r\n ConditionTreatment 10.40 0.85\r\n Item (Intercept) 6.66 \r\n ConditionTreatment 17.56 0.14\r\n Residual 6.11\r\n\r\nAgain, there are three parameters that the model estimated to capture the by-item variation:\r\nThe variation (Std.Dev.) for item intercept\r\nThe variation (Std.Dev.) for item slope\r\nThe correlation (Corr) between item intercept and item slope.\r\nAnd here is what the distribution of item random effects from model look like:\r\n\r\n\r\n\r\nOur model fitted a bivariate normal distribution with the standard deviation of item intercepts = 6.66, the standard deviation of item slopes = 10.4, and correlation = 0.14.\r\nWe can again visualize the fit of model to the distribution of the item random effects:\r\n\r\n\r\n\r\nThe model estimates a low correlation of 0.14, which is reflected in the small tilt of the ellipse. It looks like the model is capturing the distribution of the item random effects pretty well. But is the correlation parameter really that necessary here?\r\nLet’s make another depleted model, no_item_cor_model, with the correlation between item random effects removed:\r\n\r\n\r\nno_item_cor_model <- lmer(Response ~ Condition + (1+Condition|Subject) + (1+model.matrix(model)[,2]||Item),\r\n REML = FALSE, control = lmerControl('bobyqa'), data = toydata)\r\n\r\ntab_model(no_item_cor_model)\r\n\r\n\r\n\r\n \r\n\r\n\r\nResponse\r\n\r\n\r\nPredictors\r\n\r\n\r\nEstimates\r\n\r\n\r\nCI\r\n\r\n\r\np\r\n\r\n\r\n(Intercept)\r\n\r\n\r\n209.64\r\n\r\n\r\n203.49 – 215.80\r\n\r\n\r\n<0.001\r\n\r\n\r\nCondition [Treatment]\r\n\r\n\r\n35.88\r\n\r\n\r\n28.45 – 43.31\r\n\r\n\r\n<0.001\r\n\r\n\r\nRandom Effects\r\n\r\n\r\nσ2\r\n\r\n37.37\r\n\r\n\r\nτ00Subject\r\n\r\n636.98\r\n\r\n\r\nτ00Item\r\n\r\n44.55\r\n\r\n\r\nτ00Item.1\r\n\r\n310.22\r\n\r\n\r\nτ11Subject.ConditionTreatment\r\n\r\n108.08\r\n\r\n\r\nρ01Subject\r\n\r\n0.85\r\n\r\n\r\nICC\r\n\r\n\r\n0.96\r\n\r\n\r\nN Subject\r\n\r\n80\r\n\r\n\r\nN Item\r\n\r\n24\r\n\r\n\r\nObservations\r\n\r\n\r\n1920\r\n\r\n\r\nMarginal R2 / Conditional R2\r\n\r\n0.244 / 0.972\r\n\r\n\r\nAgain, the output of the depleted model printed here does not differ that much from the output of model. We can see also get a sense of this by visualizing the fit of no_item_cor_model to the distribution of item random effects:\r\n\r\n\r\n\r\nWe can see this more clearly with a side-by-side comparison of model fit by model (blue) and no_item_cor_model (red):\r\n\r\n\r\n\r\nDoesn’t seem like there are big differences here, but we have to run some statistics to be sure. So let’s perform another log likelihood ratio test:\r\n\r\n\r\nanova(no_item_cor_model, model)\r\n\r\n\r\n Data: toydata\r\n Models:\r\n no_item_cor_model: Response ~ Condition + (1 + Condition | Subject) + (1 + model.matrix(model)[, \r\n no_item_cor_model: 2] || Item)\r\n model: Response ~ Condition + (1 + Condition | Subject) + (1 + Condition | \r\n model: Item)\r\n npar AIC BIC logLik deviance Chisq Df Pr(>Chisq)\r\n no_item_cor_model 8 13265 13310 -6625 13249 \r\n model 9 13267 13317 -6624 13249 0.47 1 0.49\r\n\r\n\r\n\r\n\r\nFirst, for sanity check, we see that no_item_cor_model has one less Df than model, which is what we’d expect if no_item_cor_model indeed lacks the correlation parameter for item random effects. Next, we see that the value of Pr(>Chisq) is very high, at 0.49, suggesting that the models are not significantly different. This is corroborated by the very small differences between the models’ AIC and BIC values. These small differences here are likely reducible to the fact that AIC and BIC penalize more number of parameters (as a way of balancing model fit with model complexity). In fact, the differences in AIC between the models is approximately 2, which is exactly what you’d expect if you added a redundant parameter with no additional explanatory power to the model.\r\nIn sum, we see that when modeling our dataset toydata, estimating a correlation parameter for subject random effects improves model fit, while doing so for item random effects doesn’t as much.\r\nConclusion and implications for model building\r\nMy main goal here was to simply go over what the correlation parameter in mixed-effects models is, so the question of whether we should be including certain correlation parameter(s) in our models are beyond the scope of this discussion (and should be handled on a case-by-case basis). It’s also something that I’m in the process of learning, so I don’t have a good answer to it yet. But my personal view (which may change later with more knowledge and experience) is to keep correlation parameters in the model unless they make the model fail to converge. So in the case of the correlation parameter for item random effects in model that we discussed above, I’d personally keep that in since we didn’t run into any convergence issues fitting the maximal model. In general, if there’s no meaningful difference either way, I err towards leaving the correlation parameter in there. In other words, I try to keep the model as maximal as possible without overparameterizing it (Barr et al., 2013).\r\nI don’t think that the spirit of this message is really controversial, and the more challenging part of this is putting it into practice. We not only need to balance model fit with model complexity, but we also often need to navigate conflicts between important considerations from statistical theory and from whatever domain our research is in (linguistics, psychology, etc.).\r\nTo resolve this, a lot of people have streamlined different methods of reducing the complexity of the random effects structure in a statistically motivated way. One such example is using Principal Components Analysis (PCA) (suggested in Bates et al., 2015). In Section 3 of their paper, Bates and colleagues outline a procedure for iterative model reduction which involves PCA (now available as rePCA() in the lme4 package) to determine how many random effect terms are sufficient to capture the variance in the random effects. This is still not a perfect solution, of course, but it’s a good next step for putting this knowledge into practice. Or you can just do fancy Bayesian analyses and avoid all these problems, so I hear\r\nAnyways, that’s it for my notes. Here’s the code that generated toydata:\r\n\r\n\r\n###########\r\n## Setup ##\r\n###########\r\n\r\n# Load Packages (make sure dplyr::filter() isn't makes by MASS:filter())\r\nlibrary(MASS)\r\nlibrary(tidyverse)\r\nlibrary(lme4)\r\n\r\n# Set seed\r\nset.seed(1234)\r\n\r\n# Set number of participants and items\r\nn_subjects <- 80\r\nn_items <- 24\r\n\r\n#################\r\n## Make trials ##\r\n#################\r\n\r\n# Generate levels\r\nSubject <- gl(n_subjects, n_items)\r\nItem <- rep(gl(n_items, 1), n_subjects)\r\nCondition <- factor(rep(c(rep(c(\"Control\", \"Treatment\"), n_items/2),\r\n rep(c(\"Treatment\", \"Control\"), n_items/2)),\r\n n_subjects/2))\r\n\r\n# Treatment coding\r\nCondition_coded <- ifelse(Condition == \"Control\", 0, 1)\r\n\r\n# Combine into trials\r\nData <- tibble(Subject, Item, Condition, Condition_coded)\r\n\r\n#############################\r\n## Add Intercept and Slope ##\r\n#############################\r\n\r\n# Add intercept\r\nData$Intercept <- 200\r\n\r\n# Add slope\r\nData$Slope <- ifelse(Data$Condition == \"Treatment\", 30, 0)\r\n\r\n########################\r\n## Add Random Effects ##\r\n########################\r\n\r\n# By-subject variation in intercept and slope (sampled from bivariate normal)\r\nsd_subj_intercept <- 25\r\nsd_subj_slope <- 10\r\nsubj_ranef_cor <- 0.8\r\n\r\nsubj_ranef <- mvrnorm(n_subjects,\r\n # means of two normals are both 0\r\n c(\"Intercept\" = 0, \"Slope\" = 0),\r\n # 2x2 variance-covariance matrix\r\n matrix(\r\n c(sd_subj_intercept^2,\r\n subj_ranef_cor*sd_subj_intercept*sd_subj_slope,\r\n subj_ranef_cor*sd_subj_intercept*sd_subj_slope,\r\n sd_subj_slope^2),\r\n ncol = 2)\r\n )\r\n\r\nData$Subj_intercept <- rep(subj_ranef[,\"Intercept\"], each = n_items)\r\nData$Subj_slope <- rep(subj_ranef[,\"Slope\"], each = n_items)\r\n\r\n# By-item variation in intercept and slope (sampled independently)\r\nData$Item_intercept <- rep(rnorm(n_items, sd = 5), times = n_subjects)\r\nData$Item_slope <- rep(rnorm(n_items, sd = 15), times = n_subjects)\r\n\r\n# Random noise\r\nData$Noise <- rnorm(nrow(Data), 0, 5) + rlnorm(nrow(Data), 0.5)\r\n\r\n###########################\r\n## Generate Observations ##\r\n###########################\r\n\r\nData <- Data %>%\r\n mutate(Response =\r\n Intercept +\r\n Slope * Condition_coded +\r\n Subj_intercept +\r\n Subj_slope * Condition_coded +\r\n Item_intercept +\r\n Item_slope * Condition_coded +\r\n Noise)\r\n\r\n#################\r\n## Toy Dataset ##\r\n#################\r\n\r\ntoydata <- Data %>% \r\n select(Subject, Item, Condition, Response)\r\n\r\n\r\n\r\n\r\nThis distinction is also reflected in the fact that the notation for random effect standard deviation is tau (\\(\\tau\\)), which is a Greek symbol. In statistics, Greek symbols (like \\(\\beta\\), which we may be more familiar with) refers to population-level paramters.↩︎\r\nBut what if the distribution of random effects has a mean that is not equal to zero? Well that just shifts the fixed effects estimate, so the distribution of random effects can be fully characterized by just its variance/standard deviation. This is also why you should never remove a term from fixed effects without removing it from random effects like in Response ~ 1 + (1 + Condiiton | Subject) without a good reason, because the model will assume the fixed effect of Condition to be zero.↩︎\r\nRemoving a correlation term in lmer() turns out to be actually sort of tricky if you don’t explicitly numerically code your factors - sometimes just using the double bar syntax (||) doesn’t always work. I won’t go into the details of how to do that here, but there are good discussions of doing this using model.matrix() in this Rpubs post and Section 5.4 (also Appendix E) of Frossard and Renaud (2019). I could have done numeric coding with something like mutate(data, Condition = as.integer(Condition == \"Treatment\")), but I wanted to try this way out for myself↩︎\r\nHere, \\(\\tau_{00\\ Subject.1}\\) is actually the same as the \\(\\tau_{00\\ Subject.ConditionTreatment}\\) term from the maximal model, model. I don’t know how to suppress this name change after dropping a correlation term - if you do, please let me know!↩︎\r\nThe (simplified) argument here is that having the model estimate superfluous variance components can make it more difficult for the model to detect an effect if it actually exists - i.e., can lead to a loss of power↩︎\r\n", + "preview": "posts/2020-06-07-correlation-parameter-mem/preview.png", + "last_modified": "2020-11-04T22:36:36-05:00", + "input_file": {}, + "preview_width": 1248, + "preview_height": 768 + } +] diff --git a/docs/research.html b/docs/research.html new file mode 100644 index 00000000..7b3850c6 --- /dev/null +++ b/docs/research.html @@ -0,0 +1,2649 @@ + + + + + + + + + + + + + + + + + + + + + June Choe: Research + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + + + + +
    +

    Research

    + + + +
    + + +
    + + +

    Publications

    +

    Submitted

    +

    Choe, J., Cole, J., and Yoshida, M. (Under minor +revision). The role of prosodic focus in the reanalysis of garden path +sentences: Depth of semantic processing impedes the revision of an +erroneous local analysis. https://doi.org/10.17605/OSF.IO/U6DQ5

    +

    McWeeny, S., Choi, S. J., LaTourette, A., Choe, J., +Roberts, M. Y., & Norton, E. S. (Submitted). Rapid automatized +naming as a kindergarten predictor of future reading: A +meta-analysis.

    +

    Pre-print

    +

    McWeeny, S., Choe, J., & Norton, E. (2021). +SnowGlobe: An Iterative Search Tool for Systematic Reviews and +Meta-Analyses. https://doi.org/10.17605/OSF.IO/U25RN

    +

    Conference Presentations

    +

    2022

    +

    June Choe, and Anna Papafragou. Acquisition of +subordinate nouns as pragmatic inference: Semantic alternatives modulate +subordinate meanings. Poster to be presented at the 2nd Experiments +in Linguistic Meaning (ELM) conference.

    +

    June Choe, and Anna Papafragou. Beyond the basic +level: Levels of informativeness and the acquisition of subordinate +nouns. Poster to be presented at the 35th Annual Conference on +Human Sentence Processing (HSP), 24-26 March 2022. University of +California, Santa Cruz.

    +

    2020

    +

    June Choe, Jennifer Cole, and Masaya Yoshida. +Prosodic Focus Strengthens Semantic Persistence. Poster presented at The 26th +Architectures and Mechanisms for Language Processing (AMLaP), 3-5 +September 2020. Potsdam, Germany. Abstract Video Slides

    +

    June Choe. Computer-assisted snowball search for +meta-analysis research. Poster presented at +The 2020 Undergraduate Research & Arts Exposition. 27-28 May 2020. +Northwestern University, Evanston, IL. 2nd Place Poster +Award. Abstract

    +

    2019

    +

    June Choe. Social Information in Sentence +Processing. Talk at The 2019 Undergraduate Research & Arts +Exposition. 29 May 2019. Northwestern University, Evanston, IL. Abstract

    +

    June Choe, Shayne Sloggett, Masaya Yoshida and +Annette D’Onofrio. Personae in syntactic processing: +Socially-specific agents bias expectations of verb transitivity. +Poster presented at The 32nd CUNY Conference on Human Sentence +Processing. 29-31 March 2019. University of Colorado, Boulder, CO.

    +

    D’Onofrio, Annette, June Choe and Masaya Yoshida. +Personae in syntactic processing: Socially-specific agents bias +expectations of verb transitivity. Poster presented at The 93rd +Annual Meeting of the Linguistics Society of America. 3-6 January 2019. +New York City, NY.

    +
    + + +
    + +
    +
    + + + + + +
    + + + + + + + + + diff --git a/docs/resources.html b/docs/resources.html new file mode 100644 index 00000000..e161c3fa --- /dev/null +++ b/docs/resources.html @@ -0,0 +1,2669 @@ + + + + + + + + + + + + + + + + + + + + + June Choe: Resources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Resources

    + + +

    Mostly for R and data visualization

    +
    + + +
    + +

    Linguistics

    +
      +
    • Scripting online experiments with IBEX (workshop slides & materials +with Nayoun Kim)
    • +
    +

    Data Visualization

    + +

    Packages and software

    +
      +
    • {ggtrace}: R +package for exploring, debugging, and manipulating ggplot internals by +exposing the underlying object-oriented system in functional programming +terms.

    • +
    • {penngradlings}: R +package for the University of Pennsylvania Graduate Linguistics +Society.

    • +
    • {LingWER}: R +package for linguistic analysis of Word Error Rate for evaluating +transcriptions and other speech-to-text output, using a deterministic +matrix-based search algorithm optimized for R.

    • +
    • {gridAnnotate}: R +package for interactively annotating figures from the plot pane, using +{grid} graphical objects.

    • +
    • SnowGlobe: +A tool for meta-analysis research. Developed with Jinnie Choi, Sean +McWeeny, and Elizabeth Norton, with funding from the Northwestern +University Library. Currently under development but basic features are +functional. Validation experiments and guides at OSF repo.

    • +
    +

    Tutorial Blog Posts

    +
      +
    • {ggplot2} stat_*() functions [post]

    • +
    • Custom fonts in R [post]

    • +
    • {purrr} reduce() family [post1, +post2]

    • +
    • The correlation parameter in {lme4} mixed effects models [post]

    • +
    • Shortcuts for common chain of {dplyr} functions [post]

    • +
    • Plotting highly-customizable treemaps with {treemap} and +{ggplot2} [post]

    • +
    +

    By others

    +

    Tutorials:

    + +

    Books:

    + +
    + + +
    + +
    +
    + + + + + +
    + + + + + + + + + diff --git a/docs/robots.txt b/docs/robots.txt new file mode 100644 index 00000000..60fd0c5d --- /dev/null +++ b/docs/robots.txt @@ -0,0 +1 @@ +Sitemap: http://yjunechoe.github.io/sitemap.xml \ No newline at end of file diff --git a/docs/search.json b/docs/search.json new file mode 100644 index 00000000..cf76142f --- /dev/null +++ b/docs/search.json @@ -0,0 +1,50 @@ +{ + "articles": [ + { + "path": "blog.html", + "title": "Blog Posts", + "author": [], + "contents": "\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:14:52-05:00" + }, + { + "path": "index.html", + "title": "June Choe", + "description": "Ph.D. Student in Linguistics", + "author": [], + "contents": "\r\n\r\nd-article {\r\n padding-top: 5px;\r\n border-top: 0px;\r\n}\r\n\r\nd-title h1 {\r\n text-align: center;\r\n font-family: Roboto Mono;\r\n letter-spacing: 3px;\r\n}\r\n\r\nd-title p {\r\n text-align: center;\r\n}\r\n\r\n.about p {\r\n text-align: justify;\r\n}\r\n\r\n.hero-left img {\r\n width: 100%;\r\n border-radius: 15%;\r\n border: 3px solid grey;\r\n display: block;\r\n margin-left: auto;\r\n margin-right: auto;\r\n margin-bottom: 1em;\r\n}\r\n\r\n.hero-right p {\r\n margin: 10px 0px 10px 0px;\r\n font-size: 1.2em;\r\n font-family: Roboto Slab;\r\n}\r\n\r\n.hero-right li {\r\n margin-bottom: 5px;\r\n padding-left: 10px;\r\n}\r\n\r\n@media (min-width: 1200px) {\r\n .hero-left {\r\n width:32%;\r\n float:left;\r\n }\r\n .hero-right {\r\n width:63%;\r\n float:right;\r\n }\r\n}\r\n\r\n@media (max-width: 1199px) {\r\n .hero-left img {\r\n width: 50%;\r\n }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nEducation\r\n\r\n\r\nB.A. (hons.) Northwestern University (2016–20)\r\n\r\n\r\nPh.D. University of Pennsylvania (2020 ~)\r\n\r\n\r\n\r\nInterests\r\n\r\n\r\n(Computational) Psycholinguistics\r\n\r\n\r\nLanguage Acquisition\r\n\r\n\r\nParsing / Sentence Processing\r\n\r\n\r\nProsody & Information Structure\r\n\r\n\r\n\r\n\r\n\r\n\r\nMethods: Web-based experiments, eye-tracking, self-paced\r\nreading, corpus analysis\r\n\r\n\r\n\r\n\r\nProgramming: R (fluent) |\r\nHTML/CSS/JS (proficient) | Python\r\n(coursework)\r\n\r\n\r\n\r\n\r\nabout\r\n\r\n\r\nI am a second year PhD student in Linguistics at\r\nthe University of Pennsylvania. I am a psycholinguist broadly\r\ninterested in experimental approaches to studying meaning, of various\r\nflavors. I use computational and behavioral methods to study how\r\ncomprehenders parse linguistic input, both in real time and at different\r\nstages of language development. My advisor is Anna Papafragou and I am a\r\nmember of the Language &\r\nCognition Lab.\r\nI received my B.A. in Linguistics from Northwestern University, where\r\nI worked with Jennifer\r\nCole, Masaya\r\nYoshida, and Annette\r\nD’Onofrio. I also worked as a research assistant for (and still\r\ncollaborate with) the Language, Education, and\r\nReading Neuroscience Lab) in Communication Sciences and Disorders. I\r\nwrote my thesis on the role of prosodic focus in the processing of\r\ngarden-path sentences.\r\nBeyond linguistics research, I have interests in data visualization,\r\nscience communication, and the R programming language. I read and blog about these topics\r\nin my spare time as a hobby. I’m especially passionate about improving\r\nexplanatory data viz in academic research and strongly believe that\r\nstyle is just as important as content. I am also a Penn MindCORE student\r\naffiliate and work as a data science tutor for researchers at Penn.\r\n\r\n\r\n\r\n\r\ncontact me: \r\nyjchoe@sas.upenn.edu\r\n\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:14:55-05:00" + }, + { + "path": "news.html", + "title": "News", + "author": [], + "contents": "\r\n\r\n\r\nd-article h2 {\r\n font-family: Rubik;\r\n font-size: 3em;\r\n text-align: center;\r\n border-bottom: 3px solid black;\r\n}\r\n\r\nd-article h3 {\r\n font-size: 1.5em;\r\n text-align: center;\r\n font-variant: small-caps;\r\n font-family: Bitter;\r\n letter-spacing: .2em;\r\n}\r\n\r\nli::marker {\r\n font-size: 1.2em;\r\n}\r\n\r\n2021\r\nJuly\r\nMy tutorial\r\non custom fonts in R was featured as a highlight on\r\nthe R\r\nWeekly podcast!\r\nJune\r\nI gave a talk\r\nat RLadies philly on using\r\nicon fonts for data viz! I also wrote a follow-up blog\r\npost that goes deeper into font rendering in R.\r\nMay\r\nSnowGlobe, a\r\nproject started in my undergrad, was featured in an article\r\nby the Northwestern University Library. We also had a workshop\r\nfor SnowGlobe which drew participants from over a hundred\r\nuniversities!\r\nJanuary\r\nI joined Dr. Nayoun Kim\r\nfor a workshop\r\non experimental syntax held at Sungkyunkwan University (Korea). I\r\nhelped design materials\r\nfor a session on scripting online experiments with\r\nIBEX, including interactive slides\r\nmade with R!\r\n2020\r\nNovember\r\nI joined designer Will\r\nChase on his stream to talk\r\nabout the psycholinguistics of speech production for a data viz project\r\non Michael’s speech errors in The Office. It was a very cool and unique\r\nopportunity to bring my two interests together!\r\nOctober\r\nMy tutorial\r\non {ggplot2} stat_*() functions was featured as a\r\nhighlight on the R Weekly podcast, which\r\ncurates weekly updates from the R community.\r\nI became a data science tutor at MindCORE to help researchers\r\nat Penn with data visualization and R programming.\r\nSeptember\r\nI have moved to Philadelphia to start my PhD in\r\nLinguistics at the University of Pennsylvania!\r\nI presented a poster at AMLaP on my undergrad\r\nthesis research with my advisors Jennifer Cole and Masaya\r\nYoshida.\r\nJune\r\nI graduated from Northwestern University with a\r\nB.A. in Linguistics (with honors)! I was also elected into Phi Beta\r\nKappa and appointed as the Senior Marshal for Linguistics.\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:14:57-05:00" + }, + { + "path": "research.html", + "title": "Research", + "author": [], + "contents": "\r\n\r\nContents\r\nPublications\r\nSubmitted\r\nPre-print\r\n\r\nConference Presentations\r\n2022\r\n2020\r\n2019\r\n\r\n\r\n\r\np {\r\n font-family: Roboto;\r\n text-align: justify;\r\n}\r\nPublications\r\nSubmitted\r\nChoe, J., Cole, J., and Yoshida, M. (Under minor\r\nrevision). The role of prosodic focus in the reanalysis of garden path\r\nsentences: Depth of semantic processing impedes the revision of an\r\nerroneous local analysis. https://doi.org/10.17605/OSF.IO/U6DQ5\r\nMcWeeny, S., Choi, S. J., LaTourette, A., Choe, J.,\r\nRoberts, M. Y., & Norton, E. S. (Submitted). Rapid automatized\r\nnaming as a kindergarten predictor of future reading: A\r\nmeta-analysis.\r\nPre-print\r\nMcWeeny, S., Choe, J., & Norton, E. (2021).\r\nSnowGlobe: An Iterative Search Tool for Systematic Reviews and\r\nMeta-Analyses. https://doi.org/10.17605/OSF.IO/U25RN\r\nConference Presentations\r\n2022\r\nJune Choe, and Anna Papafragou. Acquisition of\r\nsubordinate nouns as pragmatic inference: Semantic alternatives modulate\r\nsubordinate meanings. Poster to be presented at the 2nd Experiments\r\nin Linguistic Meaning (ELM) conference.\r\nJune Choe, and Anna Papafragou. Beyond the basic\r\nlevel: Levels of informativeness and the acquisition of subordinate\r\nnouns. Poster to be presented at the 35th Annual Conference on\r\nHuman Sentence Processing (HSP), 24-26 March 2022. University of\r\nCalifornia, Santa Cruz.\r\n2020\r\nJune Choe, Jennifer Cole, and Masaya Yoshida.\r\nProsodic Focus Strengthens Semantic Persistence. Poster presented at The 26th\r\nArchitectures and Mechanisms for Language Processing (AMLaP), 3-5\r\nSeptember 2020. Potsdam, Germany. Abstract Video Slides\r\nJune Choe. Computer-assisted snowball search for\r\nmeta-analysis research. Poster presented at\r\nThe 2020 Undergraduate Research & Arts Exposition. 27-28 May 2020.\r\nNorthwestern University, Evanston, IL. 2nd Place Poster\r\nAward. Abstract\r\n2019\r\nJune Choe. Social Information in Sentence\r\nProcessing. Talk at The 2019 Undergraduate Research & Arts\r\nExposition. 29 May 2019. Northwestern University, Evanston, IL. Abstract\r\nJune Choe, Shayne Sloggett, Masaya Yoshida and\r\nAnnette D’Onofrio. Personae in syntactic processing:\r\nSocially-specific agents bias expectations of verb transitivity.\r\nPoster presented at The 32nd CUNY Conference on Human Sentence\r\nProcessing. 29-31 March 2019. University of Colorado, Boulder, CO.\r\nD’Onofrio, Annette, June Choe and Masaya Yoshida.\r\nPersonae in syntactic processing: Socially-specific agents bias\r\nexpectations of verb transitivity. Poster presented at The 93rd\r\nAnnual Meeting of the Linguistics Society of America. 3-6 January 2019.\r\nNew York City, NY.\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:14:59-05:00" + }, + { + "path": "resources.html", + "title": "Resources", + "description": "Mostly for R and data visualization\n", + "author": [], + "contents": "\r\n\r\nContents\r\nLinguistics\r\nData Visualization\r\nPackages and software\r\nTutorial Blog Posts\r\nBy others\r\n\r\nLinguistics\r\nScripting online experiments with IBEX (workshop slides & materials\r\nwith Nayoun Kim)\r\nData Visualization\r\n{ggplot2} style guide and showcase - most\r\nrecent version (2/10/2021)\r\nCracking open the internals of ggplot: A {ggtrace} showcase - slides\r\nPackages and software\r\n{ggtrace}: R\r\npackage for exploring, debugging, and manipulating ggplot internals by\r\nexposing the underlying object-oriented system in functional programming\r\nterms.\r\n{penngradlings}: R\r\npackage for the University of Pennsylvania Graduate Linguistics\r\nSociety.\r\n{LingWER}: R\r\npackage for linguistic analysis of Word Error Rate for evaluating\r\ntranscriptions and other speech-to-text output, using a deterministic\r\nmatrix-based search algorithm optimized for R.\r\n{gridAnnotate}: R\r\npackage for interactively annotating figures from the plot pane, using\r\n{grid} graphical objects.\r\nSnowGlobe:\r\nA tool for meta-analysis research. Developed with Jinnie Choi, Sean\r\nMcWeeny, and Elizabeth Norton, with funding from the Northwestern\r\nUniversity Library. Currently under development but basic features are\r\nfunctional. Validation experiments and guides at OSF repo.\r\nTutorial Blog Posts\r\n{ggplot2} stat_*() functions [post]\r\nCustom fonts in R [post]\r\n{purrr} reduce() family [post1,\r\npost2]\r\nThe correlation parameter in {lme4} mixed effects models [post]\r\nShortcuts for common chain of {dplyr} functions [post]\r\nPlotting highly-customizable treemaps with {treemap} and\r\n{ggplot2} [post]\r\nBy others\r\nTutorials:\r\nA\r\nggplot2 Tutorial for Beautiful Plotting in R by Cédric\r\nScherer\r\nggplot2\r\nWizardry Hands-On by Cédric Scherer\r\nggplot2\r\nworkshop by Thomas Lin Pedersen\r\nBooks:\r\nR for Data Science by\r\nHadley Wickham and Garrett Grolemund\r\nR Markdown: The\r\nDefinitive Guide by Yihui Xie, J. J. Allaire, and Garrett\r\nGrolemund\r\nggplot2: elegant graphics for\r\ndata analysis by Hadley Wickham, Danielle Navarro, and Thomas Lin\r\nPedersen\r\nFundamentals of Data\r\nVisualization by Claus O. Wilke\r\nEfficient R\r\nProgramming by Colin Gillespie and Robin Lovelace\r\nAdvanced R by Hadley\r\nWickham\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:15:02-05:00" + }, + { + "path": "visualizations.html", + "title": "Data Visualizations", + "description": "Select data visualizations", + "author": [], + "contents": "\r\n\r\n\r\nd-article img {\r\n padding: 25px 0px 15px 0px;\r\n border-top: 1px solid #2f2f2f;\r\n}\r\n\r\n.l-body p:first-child img {\r\n border-top: 0px;\r\n padding-top: 0px;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "last_modified": "2022-03-10T00:15:07-05:00" + } + ], + "collections": ["posts/posts.json"] +} diff --git a/docs/site_libs/anchor-4.2.2/anchor.min.js b/docs/site_libs/anchor-4.2.2/anchor.min.js new file mode 100644 index 00000000..26908ec1 --- /dev/null +++ b/docs/site_libs/anchor-4.2.2/anchor.min.js @@ -0,0 +1,9 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +// +// AnchorJS - v4.2.2 - 2019-11-14 +// https://www.bryanbraun.com/anchorjs/ +// Copyright (c) 2019 Bryan Braun; Licensed MIT +// +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +!function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";return function(A){function f(A){A.icon=A.hasOwnProperty("icon")?A.icon:"",A.visible=A.hasOwnProperty("visible")?A.visible:"hover",A.placement=A.hasOwnProperty("placement")?A.placement:"right",A.ariaLabel=A.hasOwnProperty("ariaLabel")?A.ariaLabel:"Anchor",A.class=A.hasOwnProperty("class")?A.class:"",A.base=A.hasOwnProperty("base")?A.base:"",A.truncate=A.hasOwnProperty("truncate")?Math.floor(A.truncate):64,A.titleText=A.hasOwnProperty("titleText")?A.titleText:""}function p(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new Error("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}this.options=A||{},this.elements=[],f(this.options),this.isTouchDevice=function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var e,t,i,n,o,s,a,r,c,h,l,u,d=[];if(f(this.options),"touch"===(l=this.options.visible)&&(l=this.isTouchDevice()?"always":"hover"),0===(e=p(A=A||"h2, h3, h4, h5, h6")).length)return this;for(!function(){if(null!==document.head.querySelector("style.anchorjs"))return;var A,e=document.createElement("style");e.className="anchorjs",e.appendChild(document.createTextNode("")),void 0===(A=document.head.querySelector('[rel="stylesheet"], style'))?document.head.appendChild(e):document.head.insertBefore(e,A);e.sheet.insertRule(" .anchorjs-link { opacity: 0; text-decoration: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }",e.sheet.cssRules.length),e.sheet.insertRule(" *:hover > .anchorjs-link, .anchorjs-link:focus { opacity: 1; }",e.sheet.cssRules.length),e.sheet.insertRule(" [data-anchorjs-icon]::after { content: attr(data-anchorjs-icon); }",e.sheet.cssRules.length),e.sheet.insertRule(' @font-face { font-family: "anchorjs-icons"; src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype"); }',e.sheet.cssRules.length)}(),t=document.querySelectorAll("[id]"),i=[].map.call(t,function(A){return A.id}),o=0;o\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),t=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||t||!1}}}); +// @license-end \ No newline at end of file diff --git a/docs/site_libs/autocomplete-0.37.1/autocomplete.min.js b/docs/site_libs/autocomplete-0.37.1/autocomplete.min.js new file mode 100644 index 00000000..e115402f --- /dev/null +++ b/docs/site_libs/autocomplete-0.37.1/autocomplete.min.js @@ -0,0 +1,7 @@ +/*! + * autocomplete.js 0.37.1 + * https://github.com/algolia/autocomplete.js + * Copyright 2020 Algolia, Inc. and other contributors; Licensed MIT + */ +!function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.autocomplete=b():a.autocomplete=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){"use strict";a.exports=c(1)},function(a,b,c){"use strict";function d(a,b,c,d){c=f.isArray(c)?c:[].slice.call(arguments,2);var j=e(a).each(function(a,f){var j=e(f),k=new i({el:j}),l=d||new h({input:j,eventBus:k,dropdownMenuContainer:b.dropdownMenuContainer,hint:void 0===b.hint||!!b.hint,minLength:b.minLength,autoselect:b.autoselect,autoselectOnBlur:b.autoselectOnBlur,tabAutocomplete:b.tabAutocomplete,openOnFocus:b.openOnFocus,templates:b.templates,debug:b.debug,clearOnSelected:b.clearOnSelected,cssClasses:b.cssClasses,datasets:c,keyboardShortcuts:b.keyboardShortcuts,appendTo:b.appendTo,autoWidth:b.autoWidth,ariaLabel:b.ariaLabel||f.getAttribute("aria-label")});j.data(g,l)});return j.autocomplete={},f.each(["open","close","getVal","setVal","destroy","getWrapper"],function(a){j.autocomplete[a]=function(){var b,c=arguments;return j.each(function(d,f){var h=e(f).data(g);b=h[a].apply(h,c)}),b}}),j}var e=c(2);c(3).element=e;var f=c(4);f.isArray=e.isArray,f.isFunction=e.isFunction,f.isObject=e.isPlainObject,f.bind=e.proxy,f.each=function(a,b){function c(a,c){return b(c,a)}e.each(a,c)},f.map=e.map,f.mixin=e.extend,f.Event=e.Event;var g="aaAutocomplete",h=c(5),i=c(6);d.sources=h.sources,d.escapeHighlightedString=f.escapeHighlightedString;var j="autocomplete"in window,k=window.autocomplete;d.noConflict=function(){return j?window.autocomplete=k:delete window.autocomplete,d},a.exports=d},function(a,b){!function(b,c){a.exports=function(a){var b=function(){function b(a){return null==a?String(a):V[W.call(a)]||"object"}function c(a){return"function"==b(a)}function d(a){return null!=a&&a==a.window}function e(a){return null!=a&&a.nodeType==a.DOCUMENT_NODE}function f(a){return"object"==b(a)}function g(a){return f(a)&&!d(a)&&Object.getPrototypeOf(a)==Object.prototype}function h(a){var b=!!a&&"length"in a&&a.length,c=z.type(a);return"function"!=c&&!d(a)&&("array"==c||0===b||"number"==typeof b&&b>0&&b-1 in a)}function i(a){return F.call(a,function(a){return null!=a})}function j(a){return a.length>0?z.fn.concat.apply([],a):a}function k(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function l(a){return a in J?J[a]:J[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function m(a,b){return"number"!=typeof b||K[k(a)]?b:b+"px"}function n(a){var b,c;return I[a]||(b=H.createElement(a),H.body.appendChild(b),c=getComputedStyle(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),"none"==c&&(c="block"),I[a]=c),I[a]}function o(a){return"children"in a?G.call(a.children):z.map(a.childNodes,function(a){if(1==a.nodeType)return a})}function p(a,b){var c,d=a?a.length:0;for(c=0;c]*>/,M=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,N=/^(?:body|html)$/i,O=["val","css","html","text","data","width","height","offset"],P=["after","prepend","before","append"],Q=H.createElement("table"),R=H.createElement("tr"),S={tr:H.createElement("tbody"),tbody:Q,thead:Q,tfoot:Q,td:R,th:R,"*":H.createElement("div")},T=/complete|loaded|interactive/,U=/^[\w-]*$/,V={},W=V.toString,X={},Y=H.createElement("div"),Z={tabindex:"tabIndex",readonly:"readOnly",for:"htmlFor",class:"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},$=Array.isArray||function(a){return a instanceof Array};return X.matches=function(a,b){if(!b||!a||1!==a.nodeType)return!1;var c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=Y).appendChild(a),d=~X.qsa(e,b).indexOf(a),f&&Y.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return F.call(a,function(b,c){return a.indexOf(b)==c})},X.fragment=function(a,b,c){var d,e,f;return M.test(a)&&(d=z(H.createElement(RegExp.$1))),d||(a.replace&&(a=a.replace(/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,"<$1>")),b===x&&(b=L.test(a)&&RegExp.$1),b in S||(b="*"),f=S[b],f.innerHTML=""+a,d=z.each(G.call(f.childNodes),function(){f.removeChild(this)})),g(c)&&(e=z(d),z.each(c,function(a,b){O.indexOf(a)>-1?e[a](b):e.attr(a,b)})),d},X.Z=function(a,b){return new p(a,b)},X.isZ=function(a){return a instanceof X.Z},X.init=function(a,b){var d;if(!a)return X.Z();if("string"==typeof a)if(a=a.trim(),"<"==a[0]&&L.test(a))d=X.fragment(a,RegExp.$1,b),a=null;else{if(b!==x)return z(b).find(a);d=X.qsa(H,a)}else{if(c(a))return z(H).ready(a);if(X.isZ(a))return a;if($(a))d=i(a);else if(f(a))d=[a],a=null;else if(L.test(a))d=X.fragment(a.trim(),RegExp.$1,b),a=null;else{if(b!==x)return z(b).find(a);d=X.qsa(H,a)}}return X.Z(d,a)},z=function(a,b){return X.init(a,b)},z.extend=function(a){var b,c=G.call(arguments,1);return"boolean"==typeof a&&(b=a,a=c.shift()),c.forEach(function(c){q(a,c,b)}),a},X.qsa=function(a,b){var c,d="#"==b[0],e=!d&&"."==b[0],f=d||e?b.slice(1):b,g=U.test(f);return a.getElementById&&g&&d?(c=a.getElementById(f))?[c]:[]:1!==a.nodeType&&9!==a.nodeType&&11!==a.nodeType?[]:G.call(g&&!d&&a.getElementsByClassName?e?a.getElementsByClassName(f):a.getElementsByTagName(b):a.querySelectorAll(b))},z.contains=H.documentElement.contains?function(a,b){return a!==b&&a.contains(b)}:function(a,b){for(;b&&(b=b.parentNode);)if(b===a)return!0;return!1},z.type=b,z.isFunction=c,z.isWindow=d,z.isArray=$,z.isPlainObject=g,z.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},z.isNumeric=function(a){var b=Number(a),c=typeof a;return null!=a&&"boolean"!=c&&("string"!=c||a.length)&&!isNaN(b)&&isFinite(b)||!1},z.inArray=function(a,b,c){return D.indexOf.call(b,a,c)},z.camelCase=B,z.trim=function(a){return null==a?"":String.prototype.trim.call(a)},z.uuid=0,z.support={},z.expr={},z.noop=function(){},z.map=function(a,b){var c,d,e,f=[];if(h(a))for(d=0;d=0?a:a+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(a){return D.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return c(a)?this.not(this.not(a)):z(F.call(this,function(b){return X.matches(b,a)}))},add:function(a,b){return z(C(this.concat(z(a,b))))},is:function(a){return this.length>0&&X.matches(this[0],a)},not:function(a){var b=[];if(c(a)&&a.call!==x)this.each(function(c){a.call(this,c)||b.push(this)});else{var d="string"==typeof a?this.filter(a):h(a)&&c(a.item)?G.call(a):z(a);this.forEach(function(a){d.indexOf(a)<0&&b.push(a)})}return z(b)},has:function(a){return this.filter(function(){return f(a)?z.contains(this,a):z(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!f(a)?a:z(a)},last:function(){var a=this[this.length-1];return a&&!f(a)?a:z(a)},find:function(a){var b=this;return a?"object"==typeof a?z(a).filter(function(){var a=this;return D.some.call(b,function(b){return z.contains(b,a)})}):1==this.length?z(X.qsa(this[0],a)):this.map(function(){return X.qsa(this,a)}):z()},closest:function(a,b){var c=[],d="object"==typeof a&&z(a);return this.each(function(f,g){for(;g&&!(d?d.indexOf(g)>=0:X.matches(g,a));)g=g!==b&&!e(g)&&g.parentNode;g&&c.indexOf(g)<0&&c.push(g)}),z(c)},parents:function(a){for(var b=[],c=this;c.length>0;)c=z.map(c,function(a){if((a=a.parentNode)&&!e(a)&&b.indexOf(a)<0)return b.push(a),a});return r(b,a)},parent:function(a){return r(C(this.pluck("parentNode")),a)},children:function(a){return r(this.map(function(){return o(this)}),a)},contents:function(){return this.map(function(){return this.contentDocument||G.call(this.childNodes)})},siblings:function(a){return r(this.map(function(a,b){return F.call(o(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return z.map(this,function(b){return b[a]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=n(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=c(a);if(this[0]&&!b)var d=z(a).get(0),e=d.parentNode||this.length>1;return this.each(function(c){z(this).wrapAll(b?a.call(this,c):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){z(this[0]).before(a=z(a));for(var b;(b=a.children()).length;)a=b.first();z(a).append(this)}return this},wrapInner:function(a){var b=c(a);return this.each(function(c){var d=z(this),e=d.contents(),f=b?a.call(this,c):a;e.length?e.wrapAll(f):d.append(f)})},unwrap:function(){return this.parent().each(function(){z(this).replaceWith(z(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(a){return this.each(function(){var b=z(this);(a===x?"none"==b.css("display"):a)?b.show():b.hide()})},prev:function(a){return z(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return z(this.pluck("nextElementSibling")).filter(a||"*")},html:function(a){return 0 in arguments?this.each(function(b){var c=this.innerHTML;z(this).empty().append(s(this,a,b,c))}):0 in this?this[0].innerHTML:null},text:function(a){return 0 in arguments?this.each(function(b){var c=s(this,a,b,this.textContent);this.textContent=null==c?"":""+c}):0 in this?this.pluck("textContent").join(""):null},attr:function(a,b){var c;return"string"!=typeof a||1 in arguments?this.each(function(c){if(1===this.nodeType)if(f(a))for(y in a)t(this,y,a[y]);else t(this,a,s(this,b,c,this.getAttribute(a)))}):0 in this&&1==this[0].nodeType&&null!=(c=this[0].getAttribute(a))?c:x},removeAttr:function(a){return this.each(function(){1===this.nodeType&&a.split(" ").forEach(function(a){t(this,a)},this)})},prop:function(a,b){return a=Z[a]||a,1 in arguments?this.each(function(c){this[a]=s(this,b,c,this[a])}):this[0]&&this[0][a]},removeProp:function(a){return a=Z[a]||a,this.each(function(){delete this[a]})},data:function(a,b){var c="data-"+a.replace(/([A-Z])/g,"-$1").toLowerCase(),d=1 in arguments?this.attr(c,b):this.attr(c);return null!==d?v(d):x},val:function(a){return 0 in arguments?(null==a&&(a=""),this.each(function(b){this.value=s(this,a,b,this.value)})):this[0]&&(this[0].multiple?z(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(b){if(b)return this.each(function(a){var c=z(this),d=s(this,b,a,c.offset()),e=c.offsetParent().offset(),f={top:d.top-e.top,left:d.left-e.left};"static"==c.css("position")&&(f.position="relative"),c.css(f)});if(!this.length)return null;if(H.documentElement!==this[0]&&!z.contains(H.documentElement,this[0]))return{top:0,left:0};var c=this[0].getBoundingClientRect();return{left:c.left+a.pageXOffset,top:c.top+a.pageYOffset,width:Math.round(c.width),height:Math.round(c.height)}},css:function(a,c){if(arguments.length<2){var d=this[0];if("string"==typeof a){if(!d)return;return d.style[B(a)]||getComputedStyle(d,"").getPropertyValue(a)}if($(a)){if(!d)return;var e={},f=getComputedStyle(d,"");return z.each(a,function(a,b){e[b]=d.style[B(b)]||f.getPropertyValue(b)}),e}}var g="";if("string"==b(a))c||0===c?g=k(a)+":"+m(a,c):this.each(function(){this.style.removeProperty(k(a))});else for(y in a)a[y]||0===a[y]?g+=k(y)+":"+m(y,a[y])+";":this.each(function(){this.style.removeProperty(k(y))});return this.each(function(){this.style.cssText+=";"+g})},index:function(a){return a?this.indexOf(z(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return!!a&&D.some.call(this,function(a){return this.test(u(a))},l(a))},addClass:function(a){return a?this.each(function(b){if("className"in this){A=[];var c=u(this);s(this,a,b,c).split(/\s+/g).forEach(function(a){z(this).hasClass(a)||A.push(a)},this),A.length&&u(this,c+(c?" ":"")+A.join(" "))}}):this},removeClass:function(a){return this.each(function(b){if("className"in this){if(a===x)return u(this,"");A=u(this),s(this,a,b,A).split(/\s+/g).forEach(function(a){A=A.replace(l(a)," ")}),u(this,A.trim())}})},toggleClass:function(a,b){return a?this.each(function(c){var d=z(this);s(this,a,c,u(this)).split(/\s+/g).forEach(function(a){(b===x?!d.hasClass(a):b)?d.addClass(a):d.removeClass(a)})}):this},scrollTop:function(a){if(this.length){var b="scrollTop"in this[0];return a===x?b?this[0].scrollTop:this[0].pageYOffset:this.each(b?function(){this.scrollTop=a}:function(){this.scrollTo(this.scrollX,a)})}},scrollLeft:function(a){if(this.length){var b="scrollLeft"in this[0];return a===x?b?this[0].scrollLeft:this[0].pageXOffset:this.each(b?function(){this.scrollLeft=a}:function(){this.scrollTo(a,this.scrollY)})}},position:function(){if(this.length){var a=this[0],b=this.offsetParent(),c=this.offset(),d=N.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(z(a).css("margin-top"))||0,c.left-=parseFloat(z(a).css("margin-left"))||0,d.top+=parseFloat(z(b[0]).css("border-top-width"))||0,d.left+=parseFloat(z(b[0]).css("border-left-width"))||0,{top:c.top-d.top,left:c.left-d.left}}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||H.body;a&&!N.test(a.nodeName)&&"static"==z(a).css("position");)a=a.offsetParent;return a})}},z.fn.detach=z.fn.remove,["width","height"].forEach(function(a){var b=a.replace(/./,function(a){return a[0].toUpperCase()});z.fn[a]=function(c){var f,g=this[0];return c===x?d(g)?g["inner"+b]:e(g)?g.documentElement["scroll"+b]:(f=this.offset())&&f[a]:this.each(function(b){g=z(this),g.css(a,s(this,c,b,g[a]()))})}}),P.forEach(function(c,d){var e=d%2;z.fn[c]=function(){var c,f,g=z.map(arguments,function(a){var d=[];return c=b(a),"array"==c?(a.forEach(function(a){return a.nodeType!==x?d.push(a):z.zepto.isZ(a)?d=d.concat(a.get()):void(d=d.concat(X.fragment(a)))}),d):"object"==c||null==a?a:X.fragment(a)}),h=this.length>1;return g.length<1?this:this.each(function(b,c){f=e?c:c.parentNode,c=0==d?c.nextSibling:1==d?c.firstChild:2==d?c:null;var i=z.contains(H.documentElement,f);g.forEach(function(b){if(h)b=b.cloneNode(!0);else if(!f)return z(b).remove();f.insertBefore(b,c),i&&w(b,function(b){if(!(null==b.nodeName||"SCRIPT"!==b.nodeName.toUpperCase()||b.type&&"text/javascript"!==b.type||b.src)){var c=b.ownerDocument?b.ownerDocument.defaultView:a;c.eval.call(c,b.innerHTML)}})})})},z.fn[e?c+"To":"insert"+(d?"Before":"After")]=function(a){return z(a)[c](this),this}}),X.Z.prototype=p.prototype=z.fn,X.uniq=C,X.deserializeValue=v,z.zepto=X,z}();return function(b){function c(a){return a._zid||(a._zid=n++)}function d(a,b,d,g){if(b=e(b),b.ns)var h=f(b.ns);return(r[c(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||h.test(a.ns))&&(!d||c(a.fn)===c(d))&&(!g||a.sel==g)})}function e(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function f(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function g(a,b){return a.del&&!t&&a.e in u||!!b}function h(a){return v[a]||t&&u[a]||a}function i(a,d,f,i,j,l,n){var o=c(a),p=r[o]||(r[o]=[]);d.split(/\s/).forEach(function(c){if("ready"==c)return b(document).ready(f);var d=e(c);d.fn=f,d.sel=j,d.e in v&&(f=function(a){var c=a.relatedTarget;if(!c||c!==this&&!b.contains(this,c))return d.fn.apply(this,arguments)}),d.del=l;var o=l||f;d.proxy=function(b){if(b=k(b),!b.isImmediatePropagationStopped()){try{var c=Object.getOwnPropertyDescriptor(b,"data");c&&!c.writable||(b.data=i)}catch(b){}var d=o.apply(a,b._args==m?[b]:[b].concat(b._args));return d===!1&&(b.preventDefault(),b.stopPropagation()),d}},d.i=p.length,p.push(d),"addEventListener"in a&&a.addEventListener(h(d.e),d.proxy,g(d,n))})}function j(a,b,e,f,i){var j=c(a);(b||"").split(/\s/).forEach(function(b){d(a,b,e,f).forEach(function(b){delete r[j][b.i],"removeEventListener"in a&&a.removeEventListener(h(b.e),b.proxy,g(b,i))})})}function k(a,c){if(c||!a.isDefaultPrevented){c||(c=a),b.each(z,function(b,d){var e=c[b];a[b]=function(){return this[d]=w,e&&e.apply(c,arguments)},a[d]=x});try{a.timeStamp||(a.timeStamp=Date.now())}catch(a){}(c.defaultPrevented!==m?c.defaultPrevented:"returnValue"in c?c.returnValue===!1:c.getPreventDefault&&c.getPreventDefault())&&(a.isDefaultPrevented=w)}return a}function l(a){var b,c={originalEvent:a};for(b in a)y.test(b)||a[b]===m||(c[b]=a[b]);return k(c,a)}var m,n=1,o=Array.prototype.slice,p=b.isFunction,q=function(a){return"string"==typeof a},r={},s={},t="onfocusin"in a,u={focus:"focusin",blur:"focusout"},v={mouseenter:"mouseover",mouseleave:"mouseout"};s.click=s.mousedown=s.mouseup=s.mousemove="MouseEvents",b.event={add:i,remove:j},b.proxy=function(a,d){var e=2 in arguments&&o.call(arguments,2);if(p(a)){var f=function(){return a.apply(d,e?e.concat(o.call(arguments)):arguments)};return f._zid=c(a),f}if(q(d))return e?(e.unshift(a[d],a),b.proxy.apply(null,e)):b.proxy(a[d],a);throw new TypeError("expected function")},b.fn.bind=function(a,b,c){return this.on(a,b,c)},b.fn.unbind=function(a,b){return this.off(a,b)},b.fn.one=function(a,b,c,d){return this.on(a,b,c,d,1)};var w=function(){return!0},x=function(){return!1},y=/^([A-Z]|returnValue$|layer[XY]$|webkitMovement[XY]$)/,z={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};b.fn.delegate=function(a,b,c){return this.on(b,a,c)},b.fn.undelegate=function(a,b,c){return this.off(b,a,c)},b.fn.live=function(a,c){return b(document.body).delegate(this.selector,a,c),this},b.fn.die=function(a,c){return b(document.body).undelegate(this.selector,a,c),this},b.fn.on=function(a,c,d,e,f){var g,h,k=this;return a&&!q(a)?(b.each(a,function(a,b){k.on(a,c,d,b,f)}),k):(q(c)||p(e)||e===!1||(e=d,d=c,c=m),e!==m&&d!==!1||(e=d,d=m),e===!1&&(e=x),k.each(function(k,m){f&&(g=function(a){return j(m,a.type,e),e.apply(this,arguments)}),c&&(h=function(a){var d,f=b(a.target).closest(c,m).get(0);if(f&&f!==m)return d=b.extend(l(a),{currentTarget:f,liveFired:m}),(g||e).apply(f,[d].concat(o.call(arguments,1)))}),i(m,a,e,d,c,h||g)}))},b.fn.off=function(a,c,d){var e=this;return a&&!q(a)?(b.each(a,function(a,b){e.off(a,c,b)}),e):(q(c)||p(d)||d===!1||(d=c,c=m),d===!1&&(d=x),e.each(function(){j(this,a,d,c)}))},b.fn.trigger=function(a,c){return a=q(a)||b.isPlainObject(a)?b.Event(a):k(a),a._args=c,this.each(function(){a.type in u&&"function"==typeof this[a.type]?this[a.type]():"dispatchEvent"in this?this.dispatchEvent(a):b(this).triggerHandler(a,c)})},b.fn.triggerHandler=function(a,c){var e,f;return this.each(function(g,h){e=l(q(a)?b.Event(a):a),e._args=c,e.target=h,b.each(d(h,a.type||a),function(a,b){if(f=b.proxy(e),e.isImmediatePropagationStopped())return!1})}),f},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(a){b.fn[a]=function(b){return 0 in arguments?this.bind(a,b):this.trigger(a)}}),b.Event=function(a,b){q(a)||(b=a,a=b.type);var c=document.createEvent(s[a]||"Events"),d=!0;if(b)for(var e in b)"bubbles"==e?d=!!b[e]:c[e]=b[e];return c.initEvent(a,d,!0),k(c)}}(b),function(a){var b,c=[];a.fn.remove=function(){return this.each(function(){this.parentNode&&("IMG"===this.tagName&&(c.push(this),this.src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=",b&&clearTimeout(b),b=setTimeout(function(){c=[]},6e4)),this.parentNode.removeChild(this))})}}(b),function(a){function b(b,d){var i=b[h],j=i&&e[i];if(void 0===d)return j||c(b);if(j){if(d in j)return j[d];var k=g(d);if(k in j)return j[k]}return f.call(a(b),d)}function c(b,c,f){var i=b[h]||(b[h]=++a.uuid),j=e[i]||(e[i]=d(b));return void 0!==c&&(j[g(c)]=f),j}function d(b){var c={};return a.each(b.attributes||i,function(b,d){0==d.name.indexOf("data-")&&(c[g(d.name.replace("data-",""))]=a.zepto.deserializeValue(d.value))}),c}var e={},f=a.fn.data,g=a.camelCase,h=a.expando="Zepto"+ +new Date,i=[];a.fn.data=function(d,e){return void 0===e?a.isPlainObject(d)?this.each(function(b,e){a.each(d,function(a,b){c(e,a,b)})}):0 in this?b(this[0],d):void 0:this.each(function(){c(this,d,e)})},a.data=function(b,c,d){return a(b).data(c,d)},a.hasData=function(b){var c=b[h],d=c&&e[c];return!!d&&!a.isEmptyObject(d)},a.fn.removeData=function(b){return"string"==typeof b&&(b=b.split(/\s+/)),this.each(function(){var c=this[h],d=c&&e[c];d&&a.each(b||d,function(a){delete d[b?g(this):a]})})},["remove","empty"].forEach(function(b){var c=a.fn[b];a.fn[b]=function(){var a=this.find("*");return"remove"===b&&(a=a.add(this)),a.removeData(),c.call(this)}})}(b),b}(b)}(window)},function(a,b){"use strict";a.exports={element:null}},function(a,b,c){"use strict";function d(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}var e=c(3);a.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(a){if(void 0===a&&(a=navigator.userAgent),/(msie|trident)/i.test(a)){var b=a.match(/(msie |rv:)(\d+(.\d+)?)/i);if(b)return b[2]}return!1},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(a){return"number"==typeof a},toStr:function(a){return void 0===a||null===a?"":a+""},cloneDeep:function(a){var b=this.mixin({},a),c=this;return this.each(b,function(a,d){a&&(c.isArray(a)?b[d]=[].concat(a):c.isObject(a)&&(b[d]=c.cloneDeep(a)))}),b},error:function(a){throw new Error(a)},every:function(a,b){var c=!0;return a?(this.each(a,function(d,e){c&&(c=b.call(null,d,e,a)&&c)}),!!c):c},any:function(a,b){var c=!1;return a?(this.each(a,function(d,e){if(b.call(null,d,e,a))return c=!0,!1}),c):c},getUniqueId:function(){var a=0;return function(){return a++}}(),templatify:function(a){if(this.isFunction(a))return a;var b=e.element(a);return"SCRIPT"===b.prop("tagName")?function(){return b.text()}:function(){return String(a)}},defer:function(a){setTimeout(a,0)},noop:function(){},formatPrefix:function(a,b){return b?"":a+"-"},className:function(a,b,c){return(c?"":".")+a+b},escapeHighlightedString:function(a,b,c){b=b||"";var e=document.createElement("div");e.appendChild(document.createTextNode(b)),c=c||"";var f=document.createElement("div");f.appendChild(document.createTextNode(c));var g=document.createElement("div");return g.appendChild(document.createTextNode(a)),g.innerHTML.replace(RegExp(d(e.innerHTML),"g"),b).replace(RegExp(d(f.innerHTML),"g"),c)}}},function(a,b,c){"use strict";function d(a){var b,c;if(a=a||{},a.input||i.error("missing input"),this.isActivated=!1,this.debug=!!a.debug,this.autoselect=!!a.autoselect,this.autoselectOnBlur=!!a.autoselectOnBlur,this.openOnFocus=!!a.openOnFocus,this.minLength=i.isNumber(a.minLength)?a.minLength:1,this.autoWidth=void 0===a.autoWidth||!!a.autoWidth,this.clearOnSelected=!!a.clearOnSelected,this.tabAutocomplete=void 0===a.tabAutocomplete||!!a.tabAutocomplete,a.hint=!!a.hint,a.hint&&a.appendTo)throw new Error("[autocomplete.js] hint and appendTo options can't be used at the same time");this.css=a.css=i.mixin({},o,a.appendTo?o.appendTo:{}),this.cssClasses=a.cssClasses=i.mixin({},o.defaultClasses,a.cssClasses||{}),this.cssClasses.prefix=a.cssClasses.formattedPrefix=i.formatPrefix(this.cssClasses.prefix,this.cssClasses.noPrefix),this.listboxId=a.listboxId=[this.cssClasses.root,"listbox",i.getUniqueId()].join("-");var f=e(a);this.$node=f.wrapper;var g=this.$input=f.input;b=f.menu,c=f.hint,a.dropdownMenuContainer&&j.element(a.dropdownMenuContainer).css("position","relative").append(b.css("top","0")),g.on("blur.aa",function(a){var c=document.activeElement;i.isMsie()&&(b[0]===c||b[0].contains(c))&&(a.preventDefault(),a.stopImmediatePropagation(),i.defer(function(){g.focus()}))}),b.on("mousedown.aa",function(a){a.preventDefault()}),this.eventBus=a.eventBus||new k({el:g}),this.dropdown=new d.Dropdown({appendTo:a.appendTo,wrapper:this.$node,menu:b,datasets:a.datasets,templates:a.templates,cssClasses:a.cssClasses,minLength:this.minLength}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onSync("shown",this._onShown,this).onSync("empty",this._onEmpty,this).onSync("redrawn",this._onRedrawn,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new d.Input({input:g,hint:c}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._bindKeyboardShortcuts(a),this._setLanguageDirection()}function e(a){var b,c,d,e;b=j.element(a.input),c=j.element(n.wrapper.replace("%ROOT%",a.cssClasses.root)).css(a.css.wrapper),a.appendTo||"block"!==b.css("display")||"table"!==b.parent().css("display")||c.css("display","table-cell");var g=n.dropdown.replace("%PREFIX%",a.cssClasses.prefix).replace("%DROPDOWN_MENU%",a.cssClasses.dropdownMenu);d=j.element(g).css(a.css.dropdown).attr({role:"listbox",id:a.listboxId}),a.templates&&a.templates.dropdownMenu&&d.html(i.templatify(a.templates.dropdownMenu)()),e=b.clone().css(a.css.hint).css(f(b)),e.val("").addClass(i.className(a.cssClasses.prefix,a.cssClasses.hint,!0)).removeAttr("id name placeholder required").prop("readonly",!0).attr({"aria-hidden":"true",autocomplete:"off",spellcheck:"false",tabindex:-1}),e.removeData&&e.removeData(),b.data(h,{"aria-autocomplete":b.attr("aria-autocomplete"),"aria-expanded":b.attr("aria-expanded"),"aria-owns":b.attr("aria-owns"),autocomplete:b.attr("autocomplete"),dir:b.attr("dir"),role:b.attr("role"),spellcheck:b.attr("spellcheck"),style:b.attr("style"),type:b.attr("type")}),b.addClass(i.className(a.cssClasses.prefix,a.cssClasses.input,!0)).attr({autocomplete:"off",spellcheck:!1,role:"combobox","aria-autocomplete":a.datasets&&a.datasets[0]&&a.datasets[0].displayKey?"both":"list","aria-expanded":"false","aria-label":a.ariaLabel,"aria-owns":a.listboxId}).css(a.hint?a.css.input:a.css.inputWithNoHint);try{b.attr("dir")||b.attr("dir","auto")}catch(a){}return c=a.appendTo?c.appendTo(j.element(a.appendTo).eq(0)).eq(0):b.wrap(c).parent(),c.prepend(a.hint?e:null).append(d),{wrapper:c,input:b,hint:e,menu:d}}function f(a){return{backgroundAttachment:a.css("background-attachment"),backgroundClip:a.css("background-clip"),backgroundColor:a.css("background-color"),backgroundImage:a.css("background-image"),backgroundOrigin:a.css("background-origin"),backgroundPosition:a.css("background-position"),backgroundRepeat:a.css("background-repeat"),backgroundSize:a.css("background-size")}}function g(a,b){var c=a.find(i.className(b.prefix,b.input));i.each(c.data(h),function(a,b){void 0===a?c.removeAttr(b):c.attr(b,a)}),c.detach().removeClass(i.className(b.prefix,b.input,!0)).insertAfter(a),c.removeData&&c.removeData(h),a.remove()}var h="aaAttrs",i=c(4),j=c(3),k=c(6),l=c(7),m=c(16),n=c(18),o=c(19);i.mixin(d.prototype,{_bindKeyboardShortcuts:function(a){if(a.keyboardShortcuts){var b=this.$input,c=[];i.each(a.keyboardShortcuts,function(a){"string"==typeof a&&(a=a.toUpperCase().charCodeAt(0)),c.push(a)}),j.element(document).keydown(function(a){var d=a.target||a.srcElement,e=d.tagName;if(!d.isContentEditable&&"INPUT"!==e&&"SELECT"!==e&&"TEXTAREA"!==e){var f=a.which||a.keyCode;c.indexOf(f)!==-1&&(b.focus(),a.stopPropagation(),a.preventDefault())}})}},_onSuggestionClicked:function(a,b){var c,d={selectionMethod:"click"};(c=this.dropdown.getDatumForSuggestion(b))&&this._select(c,d)},_onCursorMoved:function(a,b){var c=this.dropdown.getDatumForCursor(),d=this.dropdown.getCurrentCursor().attr("id");this.input.setActiveDescendant(d),c&&(b&&this.input.setInputValue(c.value,!0),this.eventBus.trigger("cursorchanged",c.raw,c.datasetName))},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint(),this.eventBus.trigger("cursorremoved")},_onDatasetRendered:function(){this._updateHint(),this.eventBus.trigger("updated")},_onOpened:function(){this._updateHint(),this.input.expand(),this.eventBus.trigger("opened")},_onEmpty:function(){this.eventBus.trigger("empty")},_onRedrawn:function(){this.$node.css("top","0px"),this.$node.css("left","0px");var a=this.$input[0].getBoundingClientRect();this.autoWidth&&this.$node.css("width",a.width+"px");var b=this.$node[0].getBoundingClientRect(),c=a.bottom-b.top;this.$node.css("top",c+"px");var d=a.left-b.left;this.$node.css("left",d+"px"),this.eventBus.trigger("redrawn")},_onShown:function(){this.eventBus.trigger("shown"),this.autoselect&&this.dropdown.cursorTopSuggestion()},_onClosed:function(){this.input.clearHint(),this.input.removeActiveDescendant(),this.input.collapse(),this.eventBus.trigger("closed")},_onFocused:function(){if(this.isActivated=!0,this.openOnFocus){var a=this.input.getQuery();a.length>=this.minLength?this.dropdown.update(a):this.dropdown.empty(),this.dropdown.open()}},_onBlurred:function(){var a,b;a=this.dropdown.getDatumForCursor(),b=this.dropdown.getDatumForTopSuggestion();var c={selectionMethod:"blur"};this.debug||(this.autoselectOnBlur&&a?this._select(a,c):this.autoselectOnBlur&&b?this._select(b,c):(this.isActivated=!1,this.dropdown.empty(),this.dropdown.close()))},_onEnterKeyed:function(a,b){var c,d +;c=this.dropdown.getDatumForCursor(),d=this.dropdown.getDatumForTopSuggestion();var e={selectionMethod:"enterKey"};c?(this._select(c,e),b.preventDefault()):this.autoselect&&d&&(this._select(d,e),b.preventDefault())},_onTabKeyed:function(a,b){if(!this.tabAutocomplete)return void this.dropdown.close();var c,d={selectionMethod:"tabKey"};(c=this.dropdown.getDatumForCursor())?(this._select(c,d),b.preventDefault()):this._autocomplete(!0)},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var a=this.input.getQuery();this.dropdown.isEmpty&&a.length>=this.minLength?this.dropdown.update(a):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var a=this.input.getQuery();this.dropdown.isEmpty&&a.length>=this.minLength?this.dropdown.update(a):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(a,b){this.input.clearHintIfInvalid(),b.length>=this.minLength?this.dropdown.update(b):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var a=this.input.getLanguageDirection();this.dir!==a&&(this.dir=a,this.$node.css("direction",a),this.dropdown.setLanguageDirection(a))},_updateHint:function(){var a,b,c,d,e,f;a=this.dropdown.getDatumForTopSuggestion(),a&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(b=this.input.getInputValue(),c=l.normalizeQuery(b),d=i.escapeRegExChars(c),e=new RegExp("^(?:"+d+")(.+$)","i"),f=e.exec(a.value),f?this.input.setHint(b+f[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(a){var b,c,d,e;b=this.input.getHint(),c=this.input.getQuery(),d=a||this.input.isCursorAtEnd(),b&&c!==b&&d&&(e=this.dropdown.getDatumForTopSuggestion(),e&&this.input.setInputValue(e.value),this.eventBus.trigger("autocompleted",e.raw,e.datasetName))},_select:function(a,b){void 0!==a.value&&this.input.setQuery(a.value),this.clearOnSelected?this.setVal(""):this.input.setInputValue(a.value,!0),this._setLanguageDirection(),this.eventBus.trigger("selected",a.raw,a.datasetName,b).isDefaultPrevented()===!1&&(this.dropdown.close(),i.defer(i.bind(this.dropdown.empty,this.dropdown)))},open:function(){if(!this.isActivated){var a=this.input.getInputValue();a.length>=this.minLength?this.dropdown.update(a):this.dropdown.empty()}this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(a){a=i.toStr(a),this.isActivated?this.input.setInputValue(a):(this.input.setQuery(a),this.input.setInputValue(a,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),g(this.$node,this.cssClasses),this.$node=null},getWrapper:function(){return this.dropdown.$container[0]}}),d.Dropdown=m,d.Input=l,d.sources=c(20),a.exports=d},function(a,b,c){"use strict";function d(a){a&&a.el||e.error("EventBus initialized without el"),this.$el=f.element(a.el)}var e=c(4),f=c(3);e.mixin(d.prototype,{trigger:function(a,b,c,d){var f=e.Event("autocomplete:"+a);return this.$el.trigger(f,[b,c,d]),f}}),a.exports=d},function(a,b,c){"use strict";function d(a){var b,c,d,f,g=this;a=a||{},a.input||i.error("input is missing"),b=i.bind(this._onBlur,this),c=i.bind(this._onFocus,this),d=i.bind(this._onKeydown,this),f=i.bind(this._onInput,this),this.$hint=j.element(a.hint),this.$input=j.element(a.input).on("blur.aa",b).on("focus.aa",c).on("keydown.aa",d),0===this.$hint.length&&(this.setHint=this.getHint=this.clearHint=this.clearHintIfInvalid=i.noop),i.isMsie()?this.$input.on("keydown.aa keypress.aa cut.aa paste.aa",function(a){h[a.which||a.keyCode]||i.defer(i.bind(g._onInput,g,a))}):this.$input.on("input.aa",f),this.query=this.$input.val(),this.$overflowHelper=e(this.$input)}function e(a){return j.element('').css({position:"absolute",visibility:"hidden",whiteSpace:"pre",fontFamily:a.css("font-family"),fontSize:a.css("font-size"),fontStyle:a.css("font-style"),fontVariant:a.css("font-variant"),fontWeight:a.css("font-weight"),wordSpacing:a.css("word-spacing"),letterSpacing:a.css("letter-spacing"),textIndent:a.css("text-indent"),textRendering:a.css("text-rendering"),textTransform:a.css("text-transform")}).insertAfter(a)}function f(a,b){return d.normalizeQuery(a)===d.normalizeQuery(b)}function g(a){return a.altKey||a.ctrlKey||a.metaKey||a.shiftKey}var h;h={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"};var i=c(4),j=c(3),k=c(8);d.normalizeQuery=function(a){return(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," ")},i.mixin(d.prototype,k,{_onBlur:function(){this.resetInputValue(),this.$input.removeAttr("aria-activedescendant"),this.trigger("blurred")},_onFocus:function(){this.trigger("focused")},_onKeydown:function(a){var b=h[a.which||a.keyCode];this._managePreventDefault(b,a),b&&this._shouldTrigger(b,a)&&this.trigger(b+"Keyed",a)},_onInput:function(){this._checkInputValue()},_managePreventDefault:function(a,b){var c,d,e;switch(a){case"tab":d=this.getHint(),e=this.getInputValue(),c=d&&d!==e&&!g(b);break;case"up":case"down":c=!g(b);break;default:c=!1}c&&b.preventDefault()},_shouldTrigger:function(a,b){var c;switch(a){case"tab":c=!g(b);break;default:c=!0}return c},_checkInputValue:function(){var a,b,c;a=this.getInputValue(),b=f(a,this.query),c=!(!b||!this.query)&&this.query.length!==a.length,this.query=a,b?c&&this.trigger("whitespaceChanged",this.query):this.trigger("queryChanged",this.query)},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){void 0===a&&(a=this.query),this.$input.val(a),b?this.clearHint():this._checkInputValue()},expand:function(){this.$input.attr("aria-expanded","true")},collapse:function(){this.$input.attr("aria-expanded","false")},setActiveDescendant:function(a){this.$input.attr("aria-activedescendant",a)},removeActiveDescendant:function(){this.$input.removeAttr("aria-activedescendant")},resetInputValue:function(){this.setInputValue(this.query,!0)},getHint:function(){return this.$hint.val()},setHint:function(a){this.$hint.val(a)},clearHint:function(){this.setHint("")},clearHintIfInvalid:function(){var a,b,c,d;a=this.getInputValue(),b=this.getHint(),c=a!==b&&0===b.indexOf(a),(d=""!==a&&c&&!this.hasOverflow())||this.clearHint()},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},hasOverflow:function(){var a=this.$input.width()-2;return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>=a},isCursorAtEnd:function(){var a,b,c;return a=this.$input.val().length,b=this.$input[0].selectionStart,i.isNumber(b)?b===a:!document.selection||(c=document.selection.createRange(),c.moveStart("character",-a),a===c.text.length)},destroy:function(){this.$hint.off(".aa"),this.$input.off(".aa"),this.$hint=this.$input=this.$overflowHelper=null}}),a.exports=d},function(a,b,c){"use strict";function d(a,b,c,d){var e;if(!c)return this;for(b=b.split(l),c=d?j(c,d):c,this._callbacks=this._callbacks||{};e=b.shift();)this._callbacks[e]=this._callbacks[e]||{sync:[],async:[]},this._callbacks[e][a].push(c);return this}function e(a,b,c){return d.call(this,"async",a,b,c)}function f(a,b,c){return d.call(this,"sync",a,b,c)}function g(a){var b;if(!this._callbacks)return this;for(a=a.split(l);b=a.shift();)delete this._callbacks[b];return this}function h(a){var b,c,d,e,f;if(!this._callbacks)return this;for(a=a.split(l),d=[].slice.call(arguments,1);(b=a.shift())&&(c=this._callbacks[b]);)e=i(c.sync,this,[b].concat(d)),f=i(c.async,this,[b].concat(d)),e()&&k(f);return this}function i(a,b,c){function d(){for(var d,e=0,f=a.length;!d&&e1)for(var c=1;c1)for(var c=1;c'),this.$menu.append(this.$empty),this.$empty.hide()),this.datasets=f.map(a.datasets,function(b){return e(h.$menu,b,a.cssClasses)}),f.each(this.datasets,function(a){var b=a.getRoot();b&&0===b.parent().length&&h.$menu.append(b),a.onSync("rendered",h._onRendered,h)}),a.templates&&a.templates.footer&&(this.templates.footer=f.templatify(a.templates.footer),this.$menu.append(this.templates.footer()));var k=this;g.element(window).resize(function(){k._redraw()})}function e(a,b,c){return new d.Dataset(f.mixin({$menu:a,cssClasses:c},b))}var f=c(4),g=c(3),h=c(8),i=c(17),j=c(19);f.mixin(d.prototype,h,{_onSuggestionClick:function(a){this.trigger("suggestionClicked",g.element(a.currentTarget))},_onSuggestionMouseEnter:function(a){var b=g.element(a.currentTarget);if(!b.hasClass(f.className(this.cssClasses.prefix,this.cssClasses.cursor,!0))){this._removeCursor();var c=this;setTimeout(function(){c._setCursor(b,!1)},0)}},_onSuggestionMouseLeave:function(a){if(a.relatedTarget){if(g.element(a.relatedTarget).closest("."+f.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).length>0)return}this._removeCursor(),this.trigger("cursorRemoved")},_onRendered:function(a,b){function c(a){return a.isEmpty()}function d(a){return a.templates&&a.templates.empty}if(this.isEmpty=f.every(this.datasets,c),this.isEmpty)if(b.length>=this.minLength&&this.trigger("empty"),this.$empty)if(b.length=this.minLength?this._show():this._hide());this.trigger("datasetRendered")},_hide:function(){this.$container.hide()},_show:function(){this.$container.css("display","block"),this._redraw(),this.trigger("shown")},_redraw:function(){this.isOpen&&this.appendTo&&this.trigger("redrawn")},_getSuggestions:function(){return this.$menu.find(f.className(this.cssClasses.prefix,this.cssClasses.suggestion))},_getCursor:function(){return this.$menu.find(f.className(this.cssClasses.prefix,this.cssClasses.cursor)).first()},_setCursor:function(a,b){a.first().addClass(f.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).attr("aria-selected","true"),this.trigger("cursorMoved",b)},_removeCursor:function(){this._getCursor().removeClass(f.className(this.cssClasses.prefix,this.cssClasses.cursor,!0)).removeAttr("aria-selected")},_moveCursor:function(a){var b,c,d,e;if(this.isOpen){if(c=this._getCursor(),b=this._getSuggestions(),this._removeCursor(),d=b.index(c)+a,(d=(d+1)%(b.length+1)-1)===-1)return void this.trigger("cursorRemoved");d<-1&&(d=b.length-1),this._setCursor(e=b.eq(d),!0),this._ensureVisible(e)}},_ensureVisible:function(a){var b,c,d,e;b=a.position().top,c=b+a.height()+parseInt(a.css("margin-top"),10)+parseInt(a.css("margin-bottom"),10),d=this.$menu.scrollTop(),e=this.$menu.height()+parseInt(this.$menu.css("padding-top"),10)+parseInt(this.$menu.css("padding-bottom"),10),b<0?this.$menu.scrollTop(d+b):e0?l.element(a.$menu.find(b+"-"+this.name)[0]):l.element(m.dataset.replace("%CLASS%",this.name).replace("%PREFIX%",this.cssClasses.prefix).replace("%DATASET%",this.cssClasses.dataset)),this.$menu=a.$menu,this.clearCachedSuggestions()}function e(a){function b(b){return b[a]}return a=a||"value",k.isFunction(a)?a:b}function f(a,b){function c(a){return"

    "+b(a)+"

    "}return{empty:a.empty&&k.templatify(a.empty),header:a.header&&k.templatify(a.header),footer:a.footer&&k.templatify(a.footer),suggestion:a.suggestion||c}}function g(a){return/^[_a-zA-Z0-9-]+$/.test(a)}var h="aaDataset",i="aaValue",j="aaDatum",k=c(4),l=c(3),m=c(18),n=c(19),o=c(8);d.extractDatasetName=function(a){return l.element(a).data(h)},d.extractValue=function(a){return l.element(a).data(i)},d.extractDatum=function(a){var b=l.element(a).data(j);return"string"==typeof b&&(b=JSON.parse(b)),b},k.mixin(d.prototype,o,{_render:function(a,b){function c(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!0}].concat(b),n.templates.empty.apply(this,b)}function d(){function a(a){var b,c=m.suggestion.replace("%PREFIX%",f.cssClasses.prefix).replace("%SUGGESTION%",f.cssClasses.suggestion);return b=l.element(c).attr({role:"option",id:["option",Math.floor(1e8*Math.random())].join("-")}).append(n.templates.suggestion.apply(this,[a].concat(e))),b.data(h,n.name),b.data(i,n.displayFn(a)||void 0),b.data(j,JSON.stringify(a)),b.children().each(function(){l.element(this).css(f.css.suggestionChild)}),b}var c,d,e=[].slice.call(arguments,0),f=this,g=m.suggestions.replace("%PREFIX%",this.cssClasses.prefix).replace("%SUGGESTIONS%",this.cssClasses.suggestions);return c=l.element(g).css(this.css.suggestions),d=k.map(b,a),c.append.apply(c,d),c}function e(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!g}].concat(b),n.templates.header.apply(this,b)}function f(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!g}].concat(b),n.templates.footer.apply(this,b)}if(this.$el){var g,n=this,o=[].slice.call(arguments,2);if(this.$el.empty(),g=b&&b.length,this._isEmpty=!g,!g&&this.templates.empty)this.$el.html(c.apply(this,o)).prepend(n.templates.header?e.apply(this,o):null).append(n.templates.footer?f.apply(this,o):null);else if(g)this.$el.html(d.apply(this,o)).prepend(n.templates.header?e.apply(this,o):null).append(n.templates.footer?f.apply(this,o):null);else if(b&&!Array.isArray(b))throw new TypeError("suggestions must be an array");this.$menu&&this.$menu.addClass(this.cssClasses.prefix+(g?"with":"without")+"-"+this.name).removeClass(this.cssClasses.prefix+(g?"without":"with")+"-"+this.name),this.trigger("rendered",a)}},getRoot:function(){return this.$el},update:function(a){function b(b){if(!this.canceled&&a===this.query){var c=[].slice.call(arguments,1);this.cacheSuggestions(a,b,c),this._render.apply(this,[a,b].concat(c))}}if(this.query=a,this.canceled=!1,this.shouldFetchFromCache(a))b.apply(this,[this.cachedSuggestions].concat(this.cachedRenderExtraArgs));else{var c=this,d=function(){c.canceled||c.source(a,b.bind(c))};if(this.debounce){var e=function(){c.debounceTimeout=null,d()};clearTimeout(this.debounceTimeout),this.debounceTimeout=setTimeout(e,this.debounce)}else d()}},cacheSuggestions:function(a,b,c){this.cachedQuery=a,this.cachedSuggestions=b,this.cachedRenderExtraArgs=c},shouldFetchFromCache:function(a){return this.cache&&this.cachedQuery===a&&this.cachedSuggestions&&this.cachedSuggestions.length},clearCachedSuggestions:function(){delete this.cachedQuery,delete this.cachedSuggestions,delete this.cachedRenderExtraArgs},cancel:function(){this.canceled=!0},clear:function(){this.$el&&(this.cancel(),this.$el.empty(),this.trigger("rendered",""))},isEmpty:function(){return this._isEmpty},destroy:function(){this.clearCachedSuggestions(),this.$el=null}}),a.exports=d},function(a,b){"use strict";a.exports={wrapper:'',dropdown:'',dataset:'
    ',suggestions:'',suggestion:'
    '}},function(a,b,c){"use strict";var d=c(4),e={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none",opacity:"1"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:"0"},defaultClasses:{root:"algolia-autocomplete",prefix:"aa",noPrefix:!1,dropdownMenu:"dropdown-menu",input:"input",hint:"hint",suggestions:"suggestions",suggestion:"suggestion",cursor:"cursor",dataset:"dataset",empty:"empty"},appendTo:{wrapper:{position:"absolute",zIndex:"100",display:"none"},input:{},inputWithNoHint:{},dropdown:{display:"block"}}};d.isMsie()&&d.mixin(e.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),d.isMsie()&&d.isMsie()<=7&&d.mixin(e.input,{marginTop:"-1px"}),a.exports=e},function(a,b,c){"use strict";a.exports={hits:c(21),popularIn:c(24)}},function(a,b,c){"use strict";var d=c(4),e=c(22),f=c(23);a.exports=function(a,b){function c(c,e){a.search(c,b,function(a,b){if(a)return void d.error(a.message);e(b.hits,b)})}var g=f(a.as._ua);return g&&g[0]>=3&&g[1]>20&&(b=b||{},b.additionalUA="autocomplete.js "+e),c}},function(a,b){a.exports="0.37.1"},function(a,b){"use strict";a.exports=function(a){var b=a.match(/Algolia for JavaScript \((\d+\.)(\d+\.)(\d+)\)/)||a.match(/Algolia for vanilla JavaScript (\d+\.)(\d+\.)(\d+)/);if(b)return[b[1],b[2],b[3]]}},function(a,b,c){"use strict";var d=c(4),e=c(22),f=c(23);a.exports=function(a,b,c,g){function h(h,i){a.search(h,b,function(a,h){if(a)return void d.error(a.message);if(h.hits.length>0){var l=h.hits[0],m=d.mixin({hitsPerPage:0},c);delete m.source,delete m.index;var n=f(k.as._ua);return n&&n[0]>=3&&n[1]>20&&(b.additionalUA="autocomplete.js "+e),void k.search(j(l),m,function(a,b){if(a)return void d.error(a.message);var c=[];if(g.includeAll){var e=g.allTitle||"All departments";c.push(d.mixin({facet:{value:e,count:b.nbHits}},d.cloneDeep(l)))}d.each(b.facets,function(a,b){d.each(a,function(a,e){c.push(d.mixin({facet:{facet:b,value:e,count:a}},d.cloneDeep(l)))})});for(var f=1;f=3&&i[1]>20&&(b=b||{},b.additionalUA="autocomplete.js "+e),!c.source)return d.error("Missing 'source' key");var j=d.isFunction(c.source)?c.source:function(a){return a[c.source]};if(!c.index)return d.error("Missing 'index' key");var k=c.index;return g=g||{},h}}])}); \ No newline at end of file diff --git a/docs/site_libs/bowser-1.9.3/bowser.min.js b/docs/site_libs/bowser-1.9.3/bowser.min.js new file mode 100644 index 00000000..5866337b --- /dev/null +++ b/docs/site_libs/bowser-1.9.3/bowser.min.js @@ -0,0 +1,6 @@ +/*! + * Bowser - a browser detector + * https://github.com/ded/bowser + * MIT License | (c) Dustin Diaz 2015 + */ +!function(e,t,n){typeof module!="undefined"&&module.exports?module.exports=n():typeof define=="function"&&define.amd?define(t,n):e[t]=n()}(this,"bowser",function(){function t(t){function n(e){var n=t.match(e);return n&&n.length>1&&n[1]||""}function r(e){var n=t.match(e);return n&&n.length>1&&n[2]||""}function N(e){switch(e){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}var i=n(/(ipod|iphone|ipad)/i).toLowerCase(),s=/like android/i.test(t),o=!s&&/android/i.test(t),u=/nexus\s*[0-6]\s*/i.test(t),a=!u&&/nexus\s*[0-9]+/i.test(t),f=/CrOS/.test(t),l=/silk/i.test(t),c=/sailfish/i.test(t),h=/tizen/i.test(t),p=/(web|hpw)os/i.test(t),d=/windows phone/i.test(t),v=/SamsungBrowser/i.test(t),m=!d&&/windows/i.test(t),g=!i&&!l&&/macintosh/i.test(t),y=!o&&!c&&!h&&!p&&/linux/i.test(t),b=r(/edg([ea]|ios)\/(\d+(\.\d+)?)/i),w=n(/version\/(\d+(\.\d+)?)/i),E=/tablet/i.test(t)&&!/tablet pc/i.test(t),S=!E&&/[^-]mobi/i.test(t),x=/xbox/i.test(t),T;/opera/i.test(t)?T={name:"Opera",opera:e,version:w||n(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i)}:/opr\/|opios/i.test(t)?T={name:"Opera",opera:e,version:n(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i)||w}:/SamsungBrowser/i.test(t)?T={name:"Samsung Internet for Android",samsungBrowser:e,version:w||n(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i)}:/coast/i.test(t)?T={name:"Opera Coast",coast:e,version:w||n(/(?:coast)[\s\/](\d+(\.\d+)?)/i)}:/yabrowser/i.test(t)?T={name:"Yandex Browser",yandexbrowser:e,version:w||n(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i)}:/ucbrowser/i.test(t)?T={name:"UC Browser",ucbrowser:e,version:n(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i)}:/mxios/i.test(t)?T={name:"Maxthon",maxthon:e,version:n(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i)}:/epiphany/i.test(t)?T={name:"Epiphany",epiphany:e,version:n(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i)}:/puffin/i.test(t)?T={name:"Puffin",puffin:e,version:n(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i)}:/sleipnir/i.test(t)?T={name:"Sleipnir",sleipnir:e,version:n(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i)}:/k-meleon/i.test(t)?T={name:"K-Meleon",kMeleon:e,version:n(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i)}:d?(T={name:"Windows Phone",osname:"Windows Phone",windowsphone:e},b?(T.msedge=e,T.version=b):(T.msie=e,T.version=n(/iemobile\/(\d+(\.\d+)?)/i))):/msie|trident/i.test(t)?T={name:"Internet Explorer",msie:e,version:n(/(?:msie |rv:)(\d+(\.\d+)?)/i)}:f?T={name:"Chrome",osname:"Chrome OS",chromeos:e,chromeBook:e,chrome:e,version:n(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)}:/edg([ea]|ios)/i.test(t)?T={name:"Microsoft Edge",msedge:e,version:b}:/vivaldi/i.test(t)?T={name:"Vivaldi",vivaldi:e,version:n(/vivaldi\/(\d+(\.\d+)?)/i)||w}:c?T={name:"Sailfish",osname:"Sailfish OS",sailfish:e,version:n(/sailfish\s?browser\/(\d+(\.\d+)?)/i)}:/seamonkey\//i.test(t)?T={name:"SeaMonkey",seamonkey:e,version:n(/seamonkey\/(\d+(\.\d+)?)/i)}:/firefox|iceweasel|fxios/i.test(t)?(T={name:"Firefox",firefox:e,version:n(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i)},/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(t)&&(T.firefoxos=e,T.osname="Firefox OS")):l?T={name:"Amazon Silk",silk:e,version:n(/silk\/(\d+(\.\d+)?)/i)}:/phantom/i.test(t)?T={name:"PhantomJS",phantom:e,version:n(/phantomjs\/(\d+(\.\d+)?)/i)}:/slimerjs/i.test(t)?T={name:"SlimerJS",slimer:e,version:n(/slimerjs\/(\d+(\.\d+)?)/i)}:/blackberry|\bbb\d+/i.test(t)||/rim\stablet/i.test(t)?T={name:"BlackBerry",osname:"BlackBerry OS",blackberry:e,version:w||n(/blackberry[\d]+\/(\d+(\.\d+)?)/i)}:p?(T={name:"WebOS",osname:"WebOS",webos:e,version:w||n(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i)},/touchpad\//i.test(t)&&(T.touchpad=e)):/bada/i.test(t)?T={name:"Bada",osname:"Bada",bada:e,version:n(/dolfin\/(\d+(\.\d+)?)/i)}:h?T={name:"Tizen",osname:"Tizen",tizen:e,version:n(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i)||w}:/qupzilla/i.test(t)?T={name:"QupZilla",qupzilla:e,version:n(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i)||w}:/chromium/i.test(t)?T={name:"Chromium",chromium:e,version:n(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i)||w}:/chrome|crios|crmo/i.test(t)?T={name:"Chrome",chrome:e,version:n(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)}:o?T={name:"Android",version:w}:/safari|applewebkit/i.test(t)?(T={name:"Safari",safari:e},w&&(T.version=w)):i?(T={name:i=="iphone"?"iPhone":i=="ipad"?"iPad":"iPod"},w&&(T.version=w)):/googlebot/i.test(t)?T={name:"Googlebot",googlebot:e,version:n(/googlebot\/(\d+(\.\d+))/i)||w}:T={name:n(/^(.*)\/(.*) /),version:r(/^(.*)\/(.*) /)},!T.msedge&&/(apple)?webkit/i.test(t)?(/(apple)?webkit\/537\.36/i.test(t)?(T.name=T.name||"Blink",T.blink=e):(T.name=T.name||"Webkit",T.webkit=e),!T.version&&w&&(T.version=w)):!T.opera&&/gecko\//i.test(t)&&(T.name=T.name||"Gecko",T.gecko=e,T.version=T.version||n(/gecko\/(\d+(\.\d+)?)/i)),!T.windowsphone&&(o||T.silk)?(T.android=e,T.osname="Android"):!T.windowsphone&&i?(T[i]=e,T.ios=e,T.osname="iOS"):g?(T.mac=e,T.osname="macOS"):x?(T.xbox=e,T.osname="Xbox"):m?(T.windows=e,T.osname="Windows"):y&&(T.linux=e,T.osname="Linux");var C="";T.windows?C=N(n(/Windows ((NT|XP)( \d\d?.\d)?)/i)):T.windowsphone?C=n(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i):T.mac?(C=n(/Mac OS X (\d+([_\.\s]\d+)*)/i),C=C.replace(/[_\s]/g,".")):i?(C=n(/os (\d+([_\s]\d+)*) like mac os x/i),C=C.replace(/[_\s]/g,".")):o?C=n(/android[ \/-](\d+(\.\d+)*)/i):T.webos?C=n(/(?:web|hpw)os\/(\d+(\.\d+)*)/i):T.blackberry?C=n(/rim\stablet\sos\s(\d+(\.\d+)*)/i):T.bada?C=n(/bada\/(\d+(\.\d+)*)/i):T.tizen&&(C=n(/tizen[\/\s](\d+(\.\d+)*)/i)),C&&(T.osversion=C);var k=!T.windows&&C.split(".")[0];if(E||a||i=="ipad"||o&&(k==3||k>=4&&!S)||T.silk)T.tablet=e;else if(S||i=="iphone"||i=="ipod"||o||u||T.blackberry||T.webos||T.bada)T.mobile=e;return T.msedge||T.msie&&T.version>=10||T.yandexbrowser&&T.version>=15||T.vivaldi&&T.version>=1||T.chrome&&T.version>=20||T.samsungBrowser&&T.version>=4||T.firefox&&T.version>=20||T.safari&&T.version>=6||T.opera&&T.version>=10||T.ios&&T.osversion&&T.osversion.split(".")[0]>=6||T.blackberry&&T.version>=10.1||T.chromium&&T.version>=20?T.a=e:T.msie&&T.version<10||T.chrome&&T.version<20||T.firefox&&T.version<20||T.safari&&T.version<6||T.opera&&T.version<10||T.ios&&T.osversion&&T.osversion.split(".")[0]<6||T.chromium&&T.version<20?T.c=e:T.x=e,T}function r(e){return e.split(".").length}function i(e,t){var n=[],r;if(Array.prototype.map)return Array.prototype.map.call(e,t);for(r=0;r=0){if(n[0][t]>n[1][t])return 1;if(n[0][t]!==n[1][t])return-1;if(t===0)return 0}}function o(e,r,i){var o=n;typeof r=="string"&&(i=r,r=void 0),r===void 0&&(r=!1),i&&(o=t(i));var u=""+o.version;for(var a in e)if(e.hasOwnProperty(a)&&o[a]){if(typeof e[a]!="string")throw new Error("Browser version in the minVersion map should be a string: "+a+": "+String(e));return s([u,e[a]])<0}return r}function u(e,t,n){return!o(e,t,n)}var e=!0,n=t(typeof navigator!="undefined"?navigator.userAgent||"":"");return n.test=function(e){for(var t=0;t=8.9.0" + } +} diff --git a/docs/site_libs/core-js-2.5.3/shim.min.js b/docs/site_libs/core-js-2.5.3/shim.min.js new file mode 100644 index 00000000..3f0d5f55 --- /dev/null +++ b/docs/site_libs/core-js-2.5.3/shim.min.js @@ -0,0 +1,10 @@ +/** + * core-js 2.6.11 + * https://github.com/zloirock/core-js + * License: http://rock.mit-license.org + * © 2019 Denis Pushkarev + */ +!function(e,i,Jt){"use strict";!function(r){var e={};function __webpack_require__(t){if(e[t])return e[t].exports;var n=e[t]={i:t,l:!1,exports:{}};return r[t].call(n.exports,n,n.exports,__webpack_require__),n.l=!0,n.exports}__webpack_require__.m=r,__webpack_require__.c=e,__webpack_require__.d=function(t,n,r){__webpack_require__.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},__webpack_require__.n=function(t){var n=t&&t.__esModule?function getDefault(){return t["default"]}:function getModuleExports(){return t};return __webpack_require__.d(n,"a",n),n},__webpack_require__.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=129)}([function(t,n,r){var v=r(2),g=r(26),y=r(11),d=r(12),b=r(18),S="prototype",_=function(t,n,r){var e,i,o,u,c=t&_.F,a=t&_.G,f=t&_.P,s=t&_.B,l=a?v:t&_.S?v[n]||(v[n]={}):(v[n]||{})[S],h=a?g:g[n]||(g[n]={}),p=h[S]||(h[S]={});for(e in a&&(r=n),r)o=((i=!c&&l&&l[e]!==Jt)?l:r)[e],u=s&&i?b(o,v):f&&"function"==typeof o?b(Function.call,o):o,l&&d(l,e,o,t&_.U),h[e]!=o&&y(h,e,u),f&&p[e]!=o&&(p[e]=o)};v.core=g,_.F=1,_.G=2,_.S=4,_.P=8,_.B=16,_.W=32,_.U=64,_.R=128,t.exports=_},function(t,n,r){var e=r(4);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof i&&(i=r)},function(t,n){t.exports=function(t){try{return!!t()}catch(n){return!0}}},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n,r){var e=r(47)("wks"),i=r(33),o=r(2).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n,r){var e=r(20),i=Math.min;t.exports=function(t){return 0"+i+""};t.exports=function(n,t){var r={};r[n]=t(o),e(e.P+e.F*i(function(){var t=""[n]('"');return t!==t.toLowerCase()||3document.F=Object<\/script>"),t.close(),s=t.F;r--;)delete s[f][u[r]];return s()};t.exports=Object.create||function create(t,n){var r;return null!==t?(a[f]=i(t),r=new a,a[f]=null,r[c]=t):r=s(),n===Jt?r:o(r,n)}},function(t,n,r){var e=r(95),i=r(69).concat("length","prototype");n.f=Object.getOwnPropertyNames||function getOwnPropertyNames(t){return e(t,i)}},function(t,n,r){var e=r(2),i=r(8),o=r(7),u=r(5)("species");t.exports=function(t){var n=e[t];o&&n&&!n[u]&&i.f(n,u,{configurable:!0,get:function(){return this}})}},function(t,n){t.exports=function(t,n,r,e){if(!(t instanceof n)||e!==Jt&&e in t)throw TypeError(r+": incorrect invocation!");return t}},function(t,n,r){var h=r(18),p=r(108),v=r(81),g=r(1),y=r(6),d=r(83),b={},S={};(n=t.exports=function(t,n,r,e,i){var o,u,c,a,f=i?function(){return t}:d(t),s=h(r,e,n?2:1),l=0;if("function"!=typeof f)throw TypeError(t+" is not iterable!");if(v(f)){for(o=y(t.length);l")}),d=function(){var t=/(?:)/,n=t.exec;t.exec=function(){return n.apply(this,arguments)};var r="ab".split(t);return 2===r.length&&"a"===r[0]&&"b"===r[1]}();t.exports=function(r,t,n){var e=p(r),o=!l(function(){var t={};return t[e]=function(){return 7},7!=""[r](t)}),i=o?!l(function(){var t=!1,n=/a/;return n.exec=function(){return t=!0,null},"split"===r&&(n.constructor={},n.constructor[g]=function(){return n}),n[e](""),!t}):Jt;if(!o||!i||"replace"===r&&!y||"split"===r&&!d){var u=/./[e],c=n(h,e,""[r],function maybeCallNative(t,n,r,e,i){return n.exec===v?o&&!i?{done:!0,value:u.call(n,r,e)}:{done:!0,value:t.call(r,n,e)}:{done:!1}}),a=c[1];f(String.prototype,r,c[0]),s(RegExp.prototype,e,2==t?function(t,n){return a.call(t,this,n)}:function(t){return a.call(t,this)})}}},function(t,n,r){var e=r(2).navigator;t.exports=e&&e.userAgent||""},function(t,n,r){var d=r(2),b=r(0),S=r(12),_=r(41),x=r(30),m=r(40),w=r(39),E=r(4),O=r(3),M=r(57),I=r(43),P=r(72);t.exports=function(e,t,n,r,i,o){var u=d[e],c=u,a=i?"set":"add",f=c&&c.prototype,s={},l=function(t){var r=f[t];S(f,t,"delete"==t?function(t){return!(o&&!E(t))&&r.call(this,0===t?0:t)}:"has"==t?function has(t){return!(o&&!E(t))&&r.call(this,0===t?0:t)}:"get"==t?function get(t){return o&&!E(t)?Jt:r.call(this,0===t?0:t)}:"add"==t?function add(t){return r.call(this,0===t?0:t),this}:function set(t,n){return r.call(this,0===t?0:t,n),this})};if("function"==typeof c&&(o||f.forEach&&!O(function(){(new c).entries().next()}))){var h=new c,p=h[a](o?{}:-0,1)!=h,v=O(function(){h.has(1)}),g=M(function(t){new c(t)}),y=!o&&O(function(){for(var t=new c,n=5;n--;)t[a](n,n);return!t.has(-0)});g||(((c=t(function(t,n){w(t,c,e);var r=P(new u,t,c);return n!=Jt&&m(n,i,r[a],r),r})).prototype=f).constructor=c),(v||y)&&(l("delete"),l("has"),i&&l("get")),(y||p)&&l(a),o&&f.clear&&delete f.clear}else c=r.getConstructor(t,e,i,a),_(c.prototype,n),x.NEED=!0;return I(c,e),b(b.G+b.W+b.F*((s[e]=c)!=u),s),o||r.setStrong(c,e,i),c}},function(t,n,r){for(var e,i=r(2),o=r(11),u=r(33),c=u("typed_array"),a=u("view"),f=!(!i.ArrayBuffer||!i.DataView),s=f,l=0,h="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");l<9;)(e=i[h[l++]])?(o(e.prototype,c,!0),o(e.prototype,a,!0)):s=!1;t.exports={ABV:f,CONSTR:s,TYPED:c,VIEW:a}},function(t,n,r){t.exports=r(29)||!r(3)(function(){var t=Math.random();__defineSetter__.call(null,t,function(){}),delete r(2)[t]})},function(t,n,r){var e=r(0);t.exports=function(t){e(e.S,t,{of:function of(){for(var t=arguments.length,n=new Array(t);t--;)n[t]=arguments[t];return new this(n)}})}},function(t,n,r){var e=r(0),u=r(10),c=r(18),a=r(40);t.exports=function(t){e(e.S,t,{from:function from(t){var n,r,e,i,o=arguments[1];return u(this),(n=o!==Jt)&&u(o),t==Jt?new this:(r=[],n?(e=0,i=c(o,arguments[2],2),a(t,!1,function(t){r.push(i(t,e++))})):a(t,!1,r.push,r),new this(r))}})}},function(t,n,r){var e=r(4),i=r(2).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n,r){var e=r(2),i=r(26),o=r(29),u=r(94),c=r(8).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){var e=r(47)("keys"),i=r(33);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n,r){var e=r(2).document;t.exports=e&&e.documentElement},function(t,n,i){var r=i(4),e=i(1),o=function(t,n){if(e(t),!r(n)&&null!==n)throw TypeError(n+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,r,e){try{(e=i(18)(Function.call,i(16).f(Object.prototype,"__proto__").set,2))(t,[]),r=!(t instanceof Array)}catch(n){r=!0}return function setPrototypeOf(t,n){return o(t,n),r?t.__proto__=n:e(t,n),t}}({},!1):Jt),check:o}},function(t,n,r){var o=r(4),u=r(71).set;t.exports=function(t,n,r){var e,i=n.constructor;return i!==r&&"function"==typeof i&&(e=i.prototype)!==r.prototype&&o(e)&&u&&u(t,e),t}},function(t,n){t.exports="\t\n\x0B\f\r   ᠎              \u2028\u2029\ufeff"},function(t,n,r){var i=r(20),o=r(23);t.exports=function repeat(t){var n=String(o(this)),r="",e=i(t);if(e<0||e==Infinity)throw RangeError("Count can't be negative");for(;0>>=1)&&(n+=n))1&e&&(r+=n);return r}},function(t,n){t.exports=Math.sign||function sign(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,n){var r=Math.expm1;t.exports=!r||22025.465794806718>1,s=23===n?F(2,-24)-F(2,-77):0,l=0,h=t<0||0===t&&1/t<0?1:0;for((t=P(t))!=t||t===M?(i=t!=t?1:0,e=a):(e=A(k(t)/N),t*(o=F(2,-e))<1&&(e--,o*=2),2<=(t+=1<=e+f?s/o:s*F(2,1-f))*o&&(e++,o/=2),a<=e+f?(i=0,e=a):1<=e+f?(i=(t*o-1)*F(2,n),e+=f):(i=t*F(2,f-1)*F(2,n),e=0));8<=n;u[l++]=255&i,i/=256,n-=8);for(e=e<>1,c=i-7,a=r-1,f=t[a--],s=127&f;for(f>>=7;0>=-c,c+=n;0>8&255]}function packI32(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]}function packF64(t){return packIEEE754(t,52,8)}function packF32(t){return packIEEE754(t,23,4)}function addGetter(t,n,r){g(t[_],n,{get:function(){return this[r]}})}function get(t,n,r,e){var i=p(+r);if(t[L]>24)},setUint8:function setUint8(t,n){B.call(this,t,n<<24>>24)}},!0)}else m=function ArrayBuffer(t){s(this,m,b);var n=p(t);this._b=y.call(new Array(n),0),this[L]=n},w=function DataView(t,n,r){s(this,w,S),s(t,m,S);var e=t[L],i=l(n);if(i<0||e>24},getUint8:function getUint8(t){return get(this,1,t)[0]},getInt16:function getInt16(t){var n=get(this,2,t,arguments[1]);return(n[1]<<8|n[0])<<16>>16},getUint16:function getUint16(t){var n=get(this,2,t,arguments[1]);return n[1]<<8|n[0]},getInt32:function getInt32(t){return unpackI32(get(this,4,t,arguments[1]))},getUint32:function getUint32(t){return unpackI32(get(this,4,t,arguments[1]))>>>0},getFloat32:function getFloat32(t){return unpackIEEE754(get(this,4,t,arguments[1]),23,4)},getFloat64:function getFloat64(t){return unpackIEEE754(get(this,8,t,arguments[1]),52,8)},setInt8:function setInt8(t,n){set(this,1,t,packI8,n)},setUint8:function setUint8(t,n){set(this,1,t,packI8,n)},setInt16:function setInt16(t,n){set(this,2,t,packI16,n,arguments[2])},setUint16:function setUint16(t,n){set(this,2,t,packI16,n,arguments[2])},setInt32:function setInt32(t,n){set(this,4,t,packI32,n,arguments[2])},setUint32:function setUint32(t,n){set(this,4,t,packI32,n,arguments[2])},setFloat32:function setFloat32(t,n){set(this,4,t,packF32,n,arguments[2])}, +setFloat64:function setFloat64(t,n){set(this,8,t,packF64,n,arguments[2])}});d(m,b),d(w,S),c(w[_],u.VIEW,!0),n[b]=m,n[S]=w},function(t,n,r){t.exports=!r(7)&&!r(3)(function(){return 7!=Object.defineProperty(r(66)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){n.f=r(5)},function(t,n,r){var u=r(14),c=r(15),a=r(52)(!1),f=r(68)("IE_PROTO");t.exports=function(t,n){var r,e=c(t),i=0,o=[];for(r in e)r!=f&&u(e,r)&&o.push(r);for(;i>>0||(u.test(r)?16:10))}:e},function(t,n){t.exports=Math.log1p||function log1p(t){return-1e-8<(t=+t)&&t<1e-8?t-t*t/2:Math.log(1+t)}},function(t,n,r){var o=r(75),e=Math.pow,u=e(2,-52),c=e(2,-23),a=e(2,127)*(2-c),f=e(2,-126);t.exports=Math.fround||function fround(t){var n,r,e=Math.abs(t),i=o(t);return e>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},function(t,n,r){var e=r(0),i=Math.exp;e(e.S,"Math",{cosh:function cosh(t){return(i(t=+t)+i(-t))/2}})},function(t,n,r){var e=r(0),i=r(76);e(e.S+e.F*(i!=Math.expm1),"Math",{expm1:i})},function(t,n,r){var e=r(0);e(e.S,"Math",{fround:r(107)})},function(t,n,r){var e=r(0),a=Math.abs;e(e.S,"Math",{hypot:function hypot(t,n){for(var r,e,i=0,o=0,u=arguments.length,c=0;o>>16)*u+o*(r&i>>>16)<<16>>>0)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{log10:function log10(t){return Math.log(t)*Math.LOG10E}})},function(t,n,r){var e=r(0);e(e.S,"Math",{log1p:r(106)})},function(t,n,r){var e=r(0);e(e.S,"Math",{log2:function log2(t){return Math.log(t)/Math.LN2}})},function(t,n,r){var e=r(0);e(e.S,"Math",{sign:r(75)})},function(t,n,r){var e=r(0),i=r(76),o=Math.exp;e(e.S+e.F*r(3)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function sinh(t){return Math.abs(t=+t)<1?(i(t)-i(-t))/2:(o(t-1)-o(-t-1))*(Math.E/2)}})},function(t,n,r){var e=r(0),i=r(76),o=Math.exp;e(e.S,"Math",{tanh:function tanh(t){var n=i(t=+t),r=i(-t);return n==Infinity?1:r==Infinity?-1:(n-r)/(o(t)+o(-t))}})},function(t,n,r){var e=r(0);e(e.S,"Math",{trunc:function trunc(t){return(0>10),n%1024+56320))}return r.join("")}})},function(t,n,r){var e=r(0),u=r(15),c=r(6);e(e.S,"String",{raw:function raw(t){for(var n=u(t.raw),r=c(n.length),e=arguments.length,i=[],o=0;o]*>)/g,v=/\$([$&`']|\d\d?)/g;r(59)("replace",2,function(i,o,x,m){return[function replace(t,n){var r=i(this),e=t==Jt?Jt:t[o];return e!==Jt?e.call(t,r,n):x.call(String(r),t,n)},function(t,n){var r=m(x,t,this,n);if(r.done)return r.value;var e=w(t),i=String(this),o="function"==typeof n;o||(n=String(n));var u=e.global;if(u){var c=e.unicode;e.lastIndex=0}for(var a=[];;){var f=I(e,i);if( +null===f)break;if(a.push(f),!u)break;""===String(f[0])&&(e.lastIndex=M(i,E(e.lastIndex),c))}for(var s,l="",h=0,p=0;p>>0,f=new RegExp(t.source,(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":"")+"g");(e=l.call(f,r))&&!(c<(i=f[v])&&(u.push(r.slice(c,e.index)),1>>0;if(0===a)return[];if(0===i.length)return null===m(c,i)?[i]:[];for(var f=0,s=0,l=[];s>>0,o=r>>>0;return(n>>>0)+(e>>>0)+((i&o|(i|o)&~(i+o>>>0))>>>31)|0}})},function(t,n,r){var e=r(0);e(e.S,"Math",{isubh:function isubh(t,n,r,e){var i=t>>>0,o=r>>>0;return(n>>>0)-(e>>>0)-((~i&o|~(i^o)&i-o>>>0)>>>31)|0}})},function(t,n,r){var e=r(0);e(e.S,"Math",{imulh:function imulh(t,n){var r=+t,e=+n,i=65535&r,o=65535&e,u=r>>16,c=e>>16,a=(u*o>>>0)+(i*o>>>16);return u*c+(a>>16)+((i*c>>>0)+(65535&a)>>16)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{RAD_PER_DEG:180/Math.PI})},function(t,n,r){var e=r(0),i=Math.PI/180;e(e.S,"Math",{radians:function radians(t){return t*i}})},function(t,n,r){var e=r(0);e(e.S,"Math",{scale:r(128)})},function(t,n,r){var e=r(0);e(e.S,"Math",{umulh:function umulh(t,n){var r=+t,e=+n,i=65535&r,o=65535&e,u=r>>>16,c=e>>>16,a=(u*o>>>0)+(i*o>>>16);return u*c+(a>>>16)+((i*c>>>0)+(65535&a)>>>16)}})},function(t,n,r){var e=r(0);e(e.S,"Math",{signbit:function signbit(t){return(t=+t)!=t?t:0==t?1/t==Infinity:0new Qn(e)),e.katex=t.katex,e.password=t.password}function t(e=document){const t=new Set,n=e.querySelectorAll('d-cite');for(const i of n){const e=i.getAttribute('key').split(',');for(const n of e)t.add(n)}return[...t]}function n(e,t,n,i){if(null==e.author)return'';var a=e.author.split(' and ');let d=a.map((e)=>{if(e=e.trim(),e.match(/\{.+\}/)){var n=/\{([^}]+)\}/,i=n.exec(e);return i[1]}if(-1!=e.indexOf(','))var a=e.split(',')[0].trim(),d=e.split(',')[1];else var a=e.split(' ').slice(-1)[0].trim(),d=e.split(' ').slice(0,-1).join(' ');var r='';return void 0!=d&&(r=d.trim().split(' ').map((e)=>e.trim()[0]),r=r.join('.')+'.'),t.replace('${F}',d).replace('${L}',a).replace('${I}',r)});if(1[${i||'link'}]`}return''}function d(e,t){return'doi'in e?`${t?'
    ':''} DOI: ${e.doi}`:''}function r(e){return''+e.title+' '}function o(e){if(e){var t=r(e);return t+=a(e)+'
    ',e.author&&(t+=n(e,'${L}, ${I}',', ',' and '),(e.year||e.date)&&(t+=', ')),t+=e.year||e.date?(e.year||e.date)+'. ':'. ',t+=i(e),t+=d(e),t}return'?'}function l(e){if(e){var t='';t+=''+e.title+'',t+=a(e),t+='
    ';var r=n(e,'${I} ${L}',', ')+'.',o=i(e).trim()+' '+e.year+'. '+d(e,!0);return t+=(r+o).length'+o,t}return'?'}function s(e){for(let t of e.authors){const e=!!t.affiliation,n=!!t.affiliations;if(e)if(n)console.warn(`Author ${t.author} has both old-style ("affiliation" & "affiliationURL") and new style ("affiliations") affiliation information!`);else{let e={name:t.affiliation};t.affiliationURL&&(e.url=t.affiliationURL),t.affiliations=[e]}}return console.log(e),e}function c(e){const t=e.querySelector('script');if(t){const e=t.getAttribute('type');if('json'==e.split('/')[1]){const e=t.textContent,n=JSON.parse(e);return s(n)}console.error('Distill only supports JSON frontmatter tags anymore; no more YAML.')}else console.error('You added a frontmatter tag but did not provide a script tag with front matter data in it. Please take a look at our templates.');return{}}function u(){return-1!==['interactive','complete'].indexOf(document.readyState)}function p(e){const t='distill-prerendered-styles',n=e.getElementById(t);if(!n){const n=e.createElement('style');n.id=t,n.type='text/css';const i=e.createTextNode(bi);n.appendChild(i);const a=e.head.querySelector('script');e.head.insertBefore(n,a)}}function g(e,t){console.info('Runlevel 0: Polyfill required: '+e.name);const n=document.createElement('script');n.src=e.url,n.async=!1,t&&(n.onload=function(){t(e)}),n.onerror=function(){new Error('Runlevel 0: Polyfills failed to load script '+e.name)},document.head.appendChild(n)}function f(e,t){return t={exports:{}},e(t,t.exports),t.exports}function h(e){return e.replace(/[\t\n ]+/g,' ').replace(/{\\["^`.'acu~Hvs]( )?([a-zA-Z])}/g,(e,t,n)=>n).replace(/{\\([a-zA-Z])}/g,(e,t)=>t)}function b(e){const t=new Map,n=_i.toJSON(e);for(const i of n){for(const[e,t]of Object.entries(i.entryTags))i.entryTags[e.toLowerCase()]=h(t);i.entryTags.type=i.entryType,t.set(i.citationKey,i.entryTags)}return t}function m(e){return`@article{${e.slug}, + author = {${e.bibtexAuthors}}, + title = {${e.title}}, + journal = {${e.journal.title}}, + year = {${e.publishedYear}}, + note = {${e.url}}, + doi = {${e.doi}} +}`}function y(e){return` + +`}function x(e,t,n=document){if(0 + + d-toc { + contain: layout style; + display: block; + } + + d-toc ul { + padding-left: 0; + } + + d-toc ul > ul { + padding-left: 24px; + } + + d-toc a { + border-bottom: none; + text-decoration: none; + } + + + +

    Table of contents

    +
      `;for(const i of t){const e='D-TITLE'==i.parentElement.tagName,t=i.getAttribute('no-toc');if(e||t)continue;const a=i.textContent,d='#'+i.getAttribute('id');let r='
    • '+a+'
    • ';'H3'==i.tagName?r='
        '+r+'
      ':r+='
      ',n+=r}n+='
    ',e.innerHTML=n}function v(e){return function(t,n){return Xi(e(t),n)}}function w(e,t,n){var i=(t-e)/Rn(0,n),a=Fn(jn(i)/Nn),d=i/In(10,a);return 0<=a?(d>=Gi?10:d>=ea?5:d>=ta?2:1)*In(10,a):-In(10,-a)/(d>=Gi?10:d>=ea?5:d>=ta?2:1)}function S(e,t,n){var i=Un(t-e)/Rn(0,n),a=In(10,Fn(jn(i)/Nn)),d=i/a;return d>=Gi?a*=10:d>=ea?a*=5:d>=ta&&(a*=2),t>8|240&t>>4,15&t>>4|240&t,(15&t)<<4|15&t,1)):(t=ca.exec(e))?O(parseInt(t[1],16)):(t=ua.exec(e))?new j(t[1],t[2],t[3],1):(t=pa.exec(e))?new j(255*t[1]/100,255*t[2]/100,255*t[3]/100,1):(t=ga.exec(e))?U(t[1],t[2],t[3],t[4]):(t=fa.exec(e))?U(255*t[1]/100,255*t[2]/100,255*t[3]/100,t[4]):(t=ha.exec(e))?R(t[1],t[2]/100,t[3]/100,1):(t=ba.exec(e))?R(t[1],t[2]/100,t[3]/100,t[4]):ma.hasOwnProperty(e)?O(ma[e]):'transparent'===e?new j(NaN,NaN,NaN,0):null}function O(e){return new j(255&e>>16,255&e>>8,255&e,1)}function U(e,t,n,i){return 0>=i&&(e=t=n=NaN),new j(e,t,n,i)}function I(e){return(e instanceof L||(e=M(e)),!e)?new j:(e=e.rgb(),new j(e.r,e.g,e.b,e.opacity))}function N(e,t,n,i){return 1===arguments.length?I(e):new j(e,t,n,null==i?1:i)}function j(e,t,n,i){this.r=+e,this.g=+t,this.b=+n,this.opacity=+i}function R(e,t,n,i){return 0>=i?e=t=n=NaN:0>=n||1<=n?e=t=NaN:0>=t&&(e=NaN),new F(e,t,n,i)}function q(e){if(e instanceof F)return new F(e.h,e.s,e.l,e.opacity);if(e instanceof L||(e=M(e)),!e)return new F;if(e instanceof F)return e;e=e.rgb();var t=e.r/255,n=e.g/255,i=e.b/255,a=Hn(t,n,i),d=Rn(t,n,i),r=NaN,c=d-a,s=(d+a)/2;return c?(r=t===d?(n-i)/c+6*(ns?d+a:2-d-a,r*=60):c=0s?0:r,new F(r,c,s,e.opacity)}function F(e,t,n,i){this.h=+e,this.s=+t,this.l=+n,this.opacity=+i}function P(e,t,n){return 255*(60>e?t+(n-t)*e/60:180>e?n:240>e?t+(n-t)*(240-e)/60:t)}function H(e){if(e instanceof Y)return new Y(e.l,e.a,e.b,e.opacity);if(e instanceof X){var t=e.h*ya;return new Y(e.l,Mn(t)*e.c,Dn(t)*e.c,e.opacity)}e instanceof j||(e=I(e));var n=$(e.r),i=$(e.g),a=$(e.b),d=W((0.4124564*n+0.3575761*i+0.1804375*a)/Kn),r=W((0.2126729*n+0.7151522*i+0.072175*a)/Xn),o=W((0.0193339*n+0.119192*i+0.9503041*a)/Yn);return new Y(116*r-16,500*(d-r),200*(r-o),e.opacity)}function Y(e,t,n,i){this.l=+e,this.a=+t,this.b=+n,this.opacity=+i}function W(e){return e>Sa?In(e,1/3):e/wa+Zn}function V(e){return e>va?e*e*e:wa*(e-Zn)}function K(e){return 255*(0.0031308>=e?12.92*e:1.055*In(e,1/2.4)-0.055)}function $(e){return 0.04045>=(e/=255)?e/12.92:In((e+0.055)/1.055,2.4)}function z(e){if(e instanceof X)return new X(e.h,e.c,e.l,e.opacity);e instanceof Y||(e=H(e));var t=En(e.b,e.a)*xa;return new X(0>t?t+360:t,An(e.a*e.a+e.b*e.b),e.l,e.opacity)}function X(e,t,n,i){this.h=+e,this.c=+t,this.l=+n,this.opacity=+i}function J(e){if(e instanceof Z)return new Z(e.h,e.s,e.l,e.opacity);e instanceof j||(e=I(e));var t=e.r/255,n=e.g/255,i=e.b/255,a=(_a*i+E*t-Ta*n)/(_a+E-Ta),d=i-a,r=(D*(n-a)-B*d)/C,o=An(r*r+d*d)/(D*a*(1-a)),l=o?En(r,d)*xa-120:NaN;return new Z(0>l?l+360:l,o,a,e.opacity)}function Q(e,t,n,i){return 1===arguments.length?J(e):new Z(e,t,n,null==i?1:i)}function Z(e,t,n,i){this.h=+e,this.s=+t,this.l=+n,this.opacity=+i}function G(e,n){return function(i){return e+i*n}}function ee(e,n,i){return e=In(e,i),n=In(n,i)-e,i=1/i,function(a){return In(e+a*n,i)}}function te(e){return 1==(e=+e)?ne:function(t,n){return n-t?ee(t,n,e):La(isNaN(t)?n:t)}}function ne(e,t){var n=t-e;return n?G(e,n):La(isNaN(e)?t:e)}function ie(e){return function(){return e}}function ae(e){return function(n){return e(n)+''}}function de(e){return function t(n){function i(i,t){var a=e((i=Q(i)).h,(t=Q(t)).h),d=ne(i.s,t.s),r=ne(i.l,t.l),o=ne(i.opacity,t.opacity);return function(e){return i.h=a(e),i.s=d(e),i.l=r(In(e,n)),i.opacity=o(e),i+''}}return n=+n,i.gamma=t,i}(1)}function oe(e,t){return(t-=e=+e)?function(n){return(n-e)/t}:Pa(t)}function le(e){return function(t,n){var i=e(t=+t,n=+n);return function(e){return e<=t?0:e>=n?1:i(e)}}}function se(e){return function(n,i){var d=e(n=+n,i=+i);return function(e){return 0>=e?n:1<=e?i:d(e)}}}function ce(e,t,n,i){var a=e[0],d=e[1],r=t[0],o=t[1];return d',a=t[3]||'-',d=t[4]||'',r=!!t[5],o=t[6]&&+t[6],l=!!t[7],s=t[8]&&+t[8].slice(1),c=t[9]||'';'n'===c?(l=!0,c='g'):!$a[c]&&(c=''),(r||'0'===n&&'='===i)&&(r=!0,n='0',i='='),this.fill=n,this.align=i,this.sign=a,this.symbol=d,this.zero=r,this.width=o,this.comma=l,this.precision=s,this.type=c}function be(e){var t=e.domain;return e.ticks=function(e){var n=t();return na(n[0],n[n.length-1],null==e?10:e)},e.tickFormat=function(e,n){return ad(t(),e,n)},e.nice=function(n){null==n&&(n=10);var i,a=t(),d=0,r=a.length-1,o=a[d],l=a[r];return li&&(o=qn(o*i)/i,l=Fn(l*i)/i,i=w(o,l,n)),0i&&(a[d]=qn(o*i)/i,a[r]=Fn(l*i)/i,t(a)),e},e}function me(){var e=ge(oe,Ma);return e.copy=function(){return pe(e,me())},be(e)}function ye(e,t,n,i){function a(t){return e(t=new Date(+t)),t}return a.floor=a,a.ceil=function(n){return e(n=new Date(n-1)),t(n,1),e(n),n},a.round=function(e){var t=a(e),n=a.ceil(e);return e-t=t)for(;e(t),!n(t);)t.setTime(t-1)},function(e,i){if(e>=e)if(0>i)for(;0>=++i;)for(;t(e,-1),!n(e););else for(;0<=--i;)for(;t(e,1),!n(e););})},n&&(a.count=function(t,i){return dd.setTime(+t),rd.setTime(+i),e(dd),e(rd),Fn(n(dd,rd))},a.every=function(e){return e=Fn(e),isFinite(e)&&0e.y){var t=new Date(-1,e.m,e.d,e.H,e.M,e.S,e.L);return t.setFullYear(e.y),t}return new Date(e.y,e.m,e.d,e.H,e.M,e.S,e.L)}function we(e){if(0<=e.y&&100>e.y){var t=new Date(Date.UTC(-1,e.m,e.d,e.H,e.M,e.S,e.L));return t.setUTCFullYear(e.y),t}return new Date(Date.UTC(e.y,e.m,e.d,e.H,e.M,e.S,e.L))}function Se(e){return{y:e,m:0,d:1,H:0,M:0,S:0,L:0}}function Ce(e){function t(e,t){return function(a){var d,r,o,l=[],s=-1,i=0,c=e.length;for(a instanceof Date||(a=new Date(+a));++s=n)return-1;if(r=t.charCodeAt(l++),37===r){if(r=t.charAt(l++),o=C[r in Hd?t.charAt(l++):r],!o||0>(d=o(e,a,d)))return-1;}else if(r!=a.charCodeAt(d++))return-1}return d}var r=e.dateTime,o=e.date,l=e.time,i=e.periods,s=e.days,c=e.shortDays,u=e.months,p=e.shortMonths,g=Le(i),f=Ae(i),h=Le(s),b=Ae(s),m=Le(c),y=Ae(c),x=Le(u),k=Ae(u),v=Le(p),w=Ae(p),d={a:function(e){return c[e.getDay()]},A:function(e){return s[e.getDay()]},b:function(e){return p[e.getMonth()]},B:function(e){return u[e.getMonth()]},c:null,d:Ye,e:Ye,H:Be,I:We,j:Ve,L:Ke,m:$e,M:Xe,p:function(e){return i[+(12<=e.getHours())]},S:Je,U:Qe,w:Ze,W:Ge,x:null,X:null,y:et,Y:tt,Z:nt,"%":mt},S={a:function(e){return c[e.getUTCDay()]},A:function(e){return s[e.getUTCDay()]},b:function(e){return p[e.getUTCMonth()]},B:function(e){return u[e.getUTCMonth()]},c:null,d:it,e:it,H:at,I:dt,j:rt,L:ot,m:lt,M:st,p:function(e){return i[+(12<=e.getUTCHours())]},S:ct,U:ut,w:pt,W:gt,x:null,X:null,y:ft,Y:ht,Z:bt,"%":mt},C={a:function(e,t,a){var i=m.exec(t.slice(a));return i?(e.w=y[i[0].toLowerCase()],a+i[0].length):-1},A:function(e,t,a){var i=h.exec(t.slice(a));return i?(e.w=b[i[0].toLowerCase()],a+i[0].length):-1},b:function(e,t,a){var i=v.exec(t.slice(a));return i?(e.m=w[i[0].toLowerCase()],a+i[0].length):-1},B:function(e,t,a){var i=x.exec(t.slice(a));return i?(e.m=k[i[0].toLowerCase()],a+i[0].length):-1},c:function(e,t,n){return a(e,r,t,n)},d:je,e:je,H:qe,I:qe,j:Re,L:He,m:Ne,M:Fe,p:function(e,t,a){var i=g.exec(t.slice(a));return i?(e.p=f[i[0].toLowerCase()],a+i[0].length):-1},S:Pe,U:De,w:Ee,W:Me,x:function(e,t,n){return a(e,o,t,n)},X:function(e,t,n){return a(e,l,t,n)},y:Ue,Y:Oe,Z:Ie,"%":ze};return d.x=t(o,d),d.X=t(l,d),d.c=t(r,d),S.x=t(o,S),S.X=t(l,S),S.c=t(r,S),{format:function(e){var n=t(e+='',d);return n.toString=function(){return e},n},parse:function(e){var t=n(e+='',ve);return t.toString=function(){return e},t},utcFormat:function(e){var n=t(e+='',S);return n.toString=function(){return e},n},utcParse:function(e){var t=n(e,we);return t.toString=function(){return e},t}}}function Te(e,t,n){var i=0>e?'-':'',a=(i?-e:e)+'',d=a.length;return i+(dt?1:e>=t?0:NaN}function qt(e){return function(){this.removeAttribute(e)}}function Ft(e){return function(){this.removeAttributeNS(e.space,e.local)}}function Pt(e,t){return function(){this.setAttribute(e,t)}}function Ht(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function zt(e,t){return function(){var n=t.apply(this,arguments);null==n?this.removeAttribute(e):this.setAttribute(e,n)}}function Yt(e,t){return function(){var n=t.apply(this,arguments);null==n?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,n)}}function Bt(e){return function(){this.style.removeProperty(e)}}function Wt(e,t,n){return function(){this.style.setProperty(e,t,n)}}function Vt(e,t,n){return function(){var i=t.apply(this,arguments);null==i?this.style.removeProperty(e):this.style.setProperty(e,i,n)}}function Kt(e,t){return e.style.getPropertyValue(t)||vr(e).getComputedStyle(e,null).getPropertyValue(t)}function $t(e){return function(){delete this[e]}}function Xt(e,t){return function(){this[e]=t}}function Jt(e,t){return function(){var n=t.apply(this,arguments);null==n?delete this[e]:this[e]=n}}function Qt(e){return e.trim().split(/^|\s+/)}function Zt(e){return e.classList||new Gt(e)}function Gt(e){this._node=e,this._names=Qt(e.getAttribute('class')||'')}function en(e,t){for(var a=Zt(e),d=-1,i=t.length;++dUpdates and Corrections +

    `,e.githubCompareUpdatesUrl&&(t+=`View all changes to this article since it was first published.`),t+=` + If you see mistakes or want to suggest changes, please create an issue on GitHub.

    + `);const n=e.journal;return'undefined'!=typeof n&&'Distill'===n.title&&(t+=` +

    Reuse

    +

    Diagrams and text are licensed under Creative Commons Attribution CC-BY 4.0 with the source available on GitHub, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”.

    + `),'undefined'!=typeof e.publishedDate&&(t+=` +

    Citation

    +

    For attribution in academic contexts, please cite this work as

    +
    ${e.concatenatedAuthors}, "${e.title}", Distill, ${e.publishedYear}.
    +

    BibTeX citation

    +
    ${m(e)}
    + `),t}var An=Math.sqrt,En=Math.atan2,Dn=Math.sin,Mn=Math.cos,On=Math.PI,Un=Math.abs,In=Math.pow,Nn=Math.LN10,jn=Math.log,Rn=Math.max,qn=Math.ceil,Fn=Math.floor,Pn=Math.round,Hn=Math.min;const zn=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],Bn=['Jan.','Feb.','March','April','May','June','July','Aug.','Sept.','Oct.','Nov.','Dec.'],Wn=(e)=>10>e?'0'+e:e,Vn=function(e){const t=zn[e.getDay()].substring(0,3),n=Wn(e.getDate()),i=Bn[e.getMonth()].substring(0,3),a=e.getFullYear().toString(),d=e.getUTCHours().toString(),r=e.getUTCMinutes().toString(),o=e.getUTCSeconds().toString();return`${t}, ${n} ${i} ${a} ${d}:${r}:${o} Z`},$n=function(e){const t=Array.from(e).reduce((e,[t,n])=>Object.assign(e,{[t]:n}),{});return t},Jn=function(e){const t=new Map;for(var n in e)e.hasOwnProperty(n)&&t.set(n,e[n]);return t};class Qn{constructor(e){this.name=e.author,this.personalURL=e.authorURL,this.affiliation=e.affiliation,this.affiliationURL=e.affiliationURL,this.affiliations=e.affiliations||[]}get firstName(){const e=this.name.split(' ');return e.slice(0,e.length-1).join(' ')}get lastName(){const e=this.name.split(' ');return e[e.length-1]}}class Gn{constructor(){this.title='unnamed article',this.description='',this.authors=[],this.bibliography=new Map,this.bibliographyParsed=!1,this.citations=[],this.citationsCollected=!1,this.journal={},this.katex={},this.publishedDate=void 0}set url(e){this._url=e}get url(){if(this._url)return this._url;return this.distillPath&&this.journal.url?this.journal.url+'/'+this.distillPath:this.journal.url?this.journal.url:void 0}get githubUrl(){return this.githubPath?'https://github.com/'+this.githubPath:void 0}set previewURL(e){this._previewURL=e}get previewURL(){return this._previewURL?this._previewURL:this.url+'/thumbnail.jpg'}get publishedDateRFC(){return Vn(this.publishedDate)}get updatedDateRFC(){return Vn(this.updatedDate)}get publishedYear(){return this.publishedDate.getFullYear()}get publishedMonth(){return Bn[this.publishedDate.getMonth()]}get publishedDay(){return this.publishedDate.getDate()}get publishedMonthPadded(){return Wn(this.publishedDate.getMonth()+1)}get publishedDayPadded(){return Wn(this.publishedDate.getDate())}get publishedISODateOnly(){return this.publishedDate.toISOString().split('T')[0]}get volume(){const e=this.publishedYear-2015;if(1>e)throw new Error('Invalid publish date detected during computing volume');return e}get issue(){return this.publishedDate.getMonth()+1}get concatenatedAuthors(){if(2{return e.lastName+', '+e.firstName}).join(' and ')}get slug(){let e='';return this.authors.length&&(e+=this.authors[0].lastName.toLowerCase(),e+=this.publishedYear,e+=this.title.split(' ')[0].toLowerCase()),e||'Untitled'}get bibliographyEntries(){return new Map(this.citations.map((e)=>{const t=this.bibliography.get(e);return[e,t]}))}set bibliography(e){e instanceof Map?this._bibliography=e:'object'==typeof e&&(this._bibliography=Jn(e))}get bibliography(){return this._bibliography}static fromObject(e){const t=new Gn;return Object.assign(t,e),t}assignToObject(e){Object.assign(e,this),e.bibliography=$n(this.bibliographyEntries),e.url=this.url,e.githubUrl=this.githubUrl,e.previewURL=this.previewURL,this.publishedDate&&(e.volume=this.volume,e.issue=this.issue,e.publishedDateRFC=this.publishedDateRFC,e.publishedYear=this.publishedYear,e.publishedMonth=this.publishedMonth,e.publishedDay=this.publishedDay,e.publishedMonthPadded=this.publishedMonthPadded,e.publishedDayPadded=this.publishedDayPadded),this.updatedDate&&(e.updatedDateRFC=this.updatedDateRFC),e.concatenatedAuthors=this.concatenatedAuthors,e.bibtexAuthors=this.bibtexAuthors,e.slug=this.slug}}const ei=(e)=>{return class extends e{constructor(){super();const e={childList:!0,characterData:!0,subtree:!0},t=new MutationObserver(()=>{t.disconnect(),this.renderIfPossible(),t.observe(this,e)});t.observe(this,e)}connectedCallback(){super.connectedCallback(),this.renderIfPossible()}renderIfPossible(){this.textContent&&this.root&&this.renderContent()}renderContent(){console.error(`Your class ${this.constructor.name} must provide a custom renderContent() method!`)}}},ti=(e,t,n=!0)=>{return(i)=>{const a=document.createElement('template');return a.innerHTML=t,n&&'ShadyCSS'in window&&ShadyCSS.prepareTemplate(a,e),class extends i{static get is(){return e}constructor(){super(),this.clone=document.importNode(a.content,!0),n&&(this.attachShadow({mode:'open'}),this.shadowRoot.appendChild(this.clone))}connectedCallback(){n?'ShadyCSS'in window&&ShadyCSS.styleElement(this):this.insertBefore(this.clone,this.firstChild)}get root(){return n?this.shadowRoot:this}$(e){return this.root.querySelector(e)}$$(e){return this.root.querySelectorAll(e)}}}};var ni='/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nspan.katex-display {\n text-align: left;\n padding: 8px 0 8px 0;\n margin: 0.5em 0 0.5em 1em;\n}\n\nspan.katex {\n -webkit-font-smoothing: antialiased;\n color: rgba(0, 0, 0, 0.8);\n font-size: 1.18em;\n}\n';const ii=function(e,t,n){let i=n,a=0;for(const d=e.length;i=a&&t.slice(i,i+d)===e)return i;'\\'===n?i++:'{'===n?a++:'}'===n&&a--;i++}return-1},ai=function(e,t,n,i){const a=[];for(let d=0;d',ui=ti('d-math',` +${ci} + + +`);class T extends ei(ui(HTMLElement)){static set katexOptions(e){T._katexOptions=e,T.katexOptions.delimiters&&(T.katexAdded?T.katexLoadedCallback():T.addKatex())}static get katexOptions(){return T._katexOptions||(T._katexOptions={delimiters:[{left:'$$',right:'$$',display:!1}]}),T._katexOptions}static katexLoadedCallback(){const e=document.querySelectorAll('d-math');for(const t of e)t.renderContent();if(T.katexOptions.delimiters){const e=document.querySelector('d-article');si(e,T.katexOptions)}}static addKatex(){document.head.insertAdjacentHTML('beforeend',ci);const e=document.createElement('script');e.src='https://distill.pub/third-party/katex/katex.min.js',e.async=!0,e.onload=T.katexLoadedCallback,e.crossorigin='anonymous',document.head.appendChild(e),T.katexAdded=!0}get options(){const e={displayMode:this.hasAttribute('block')};return Object.assign(e,T.katexOptions)}connectedCallback(){super.connectedCallback(),T.katexAdded||T.addKatex()}renderContent(){if('undefined'!=typeof katex){const e=this.root.querySelector('#katex-container');katex.render(this.textContent,e,this.options)}}}T.katexAdded=!1,T.inlineMathRendered=!1,window.DMath=T;class pi extends HTMLElement{static get is(){return'd-front-matter'}constructor(){super();const e=new MutationObserver((e)=>{for(const t of e)if('SCRIPT'===t.target.nodeName||'characterData'===t.type){const e=c(this);this.notify(e)}});e.observe(this,{childList:!0,characterData:!0,subtree:!0})}notify(e){const t=new CustomEvent('onFrontMatterChanged',{detail:e,bubbles:!0});document.dispatchEvent(t)}}var gi=function(e,t){const n=e.body,i=n.querySelector('d-article');if(!i)return void console.warn('No d-article tag found; skipping adding optional components!');let a=e.querySelector('d-byline');a||(t.authors?(a=e.createElement('d-byline'),n.insertBefore(a,i)):console.warn('No authors found in front matter; please add them before submission!'));let d=e.querySelector('d-title');d||(d=e.createElement('d-title'),n.insertBefore(d,a));let r=d.querySelector('h1');r||(r=e.createElement('h1'),r.textContent=t.title,d.insertBefore(r,d.firstChild));const o='undefined'!=typeof t.password;let l=n.querySelector('d-interstitial');if(o&&!l){const i='undefined'!=typeof window,a=i&&window.location.hostname.includes('localhost');i&&a||(l=e.createElement('d-interstitial'),l.password=t.password,n.insertBefore(l,n.firstChild))}else!o&&l&&l.parentElement.removeChild(this);let s=e.querySelector('d-appendix');s||(s=e.createElement('d-appendix'),e.body.appendChild(s));let c=e.querySelector('d-footnote-list');c||(c=e.createElement('d-footnote-list'),s.appendChild(c));let u=e.querySelector('d-citation-list');u||(u=e.createElement('d-citation-list'),s.appendChild(u))};const fi=new Gn,hi={frontMatter:fi,waitingOn:{bibliography:[],citations:[]},listeners:{onCiteKeyCreated(e){const[t,n]=e.detail;if(!fi.citationsCollected)return void hi.waitingOn.citations.push(()=>hi.listeners.onCiteKeyCreated(e));if(!fi.bibliographyParsed)return void hi.waitingOn.bibliography.push(()=>hi.listeners.onCiteKeyCreated(e));const i=n.map((e)=>fi.citations.indexOf(e));t.numbers=i;const a=n.map((e)=>fi.bibliography.get(e));t.entries=a},onCiteKeyChanged(){fi.citations=t(),fi.citationsCollected=!0;for(const e of hi.waitingOn.citations.slice())e();const e=document.querySelector('d-citation-list'),n=new Map(fi.citations.map((e)=>{return[e,fi.bibliography.get(e)]}));e.citations=n;const i=document.querySelectorAll('d-cite');for(const e of i){const t=e.keys,n=t.map((e)=>fi.citations.indexOf(e));e.numbers=n;const i=t.map((e)=>fi.bibliography.get(e));e.entries=i}},onCiteKeyRemoved(e){hi.listeners.onCiteKeyChanged(e)},onBibliographyChanged(e){const t=document.querySelector('d-citation-list'),n=e.detail;fi.bibliography=n,fi.bibliographyParsed=!0;for(const t of hi.waitingOn.bibliography.slice())t();if(!fi.citationsCollected)return void hi.waitingOn.citations.push(function(){hi.listeners.onBibliographyChanged({target:e.target,detail:e.detail})});if(t.hasAttribute('distill-prerendered'))console.info('Citation list was prerendered; not updating it.');else{const e=new Map(fi.citations.map((e)=>{return[e,fi.bibliography.get(e)]}));t.citations=e}},onFootnoteChanged(){const e=document.querySelector('d-footnote-list');if(e){const t=document.querySelectorAll('d-footnote');e.footnotes=t}},onFrontMatterChanged(t){const n=t.detail;e(fi,n);const i=document.querySelector('d-interstitial');i&&('undefined'==typeof fi.password?i.parentElement.removeChild(i):i.password=fi.password);const a=document.body.hasAttribute('distill-prerendered');if(!a&&u()){gi(document,fi);const e=document.querySelector('distill-appendix');e&&(e.frontMatter=fi);const t=document.querySelector('d-byline');t&&(t.frontMatter=fi),n.katex&&(T.katexOptions=n.katex)}},DOMContentLoaded(){if(hi.loaded)return void console.warn('Controller received DOMContentLoaded but was already loaded!');if(!u())return void console.warn('Controller received DOMContentLoaded before appropriate document.readyState!');hi.loaded=!0,console.log('Runlevel 4: Controller running DOMContentLoaded');const e=document.querySelector('d-front-matter'),n=c(e);hi.listeners.onFrontMatterChanged({detail:n}),fi.citations=t(),fi.citationsCollected=!0;for(const e of hi.waitingOn.citations.slice())e();if(fi.bibliographyParsed)for(const e of hi.waitingOn.bibliography.slice())e();const i=document.querySelector('d-footnote-list');if(i){const e=document.querySelectorAll('d-footnote');i.footnotes=e}}}};const bi='/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nhtml {\n font-size: 14px;\n\tline-height: 1.6em;\n /* font-family: "Libre Franklin", "Helvetica Neue", sans-serif; */\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif;\n /*, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/\n text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\n\n@media(min-width: 768px) {\n html {\n font-size: 16px;\n }\n}\n\nbody {\n margin: 0;\n}\n\na {\n color: #004276;\n}\n\nfigure {\n margin: 0;\n}\n\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n\ntable th {\n\ttext-align: left;\n}\n\ntable thead {\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\ntable thead th {\n padding-bottom: 0.5em;\n}\n\ntable tbody :first-child td {\n padding-top: 0.5em;\n}\n\npre {\n overflow: auto;\n max-width: 100%;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1em;\n}\n\nsup, sub {\n vertical-align: baseline;\n position: relative;\n top: -0.4em;\n line-height: 1em;\n}\n\nsub {\n top: 0.4em;\n}\n\n.kicker,\n.marker {\n font-size: 15px;\n font-weight: 600;\n color: rgba(0, 0, 0, 0.5);\n}\n\n\n/* Headline */\n\n@media(min-width: 1024px) {\n d-title h1 span {\n display: block;\n }\n}\n\n/* Figure */\n\nfigure {\n position: relative;\n margin-bottom: 2.5em;\n margin-top: 1.5em;\n}\n\nfigcaption+figure {\n\n}\n\nfigure img {\n width: 100%;\n}\n\nfigure svg text,\nfigure svg tspan {\n}\n\nfigcaption,\n.figcaption {\n color: rgba(0, 0, 0, 0.6);\n font-size: 12px;\n line-height: 1.5em;\n}\n\n@media(min-width: 1024px) {\nfigcaption,\n.figcaption {\n font-size: 13px;\n }\n}\n\nfigure.external img {\n background: white;\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n padding: 18px;\n box-sizing: border-box;\n}\n\nfigcaption a {\n color: rgba(0, 0, 0, 0.6);\n}\n\nfigcaption b,\nfigcaption strong, {\n font-weight: 600;\n color: rgba(0, 0, 0, 1.0);\n}\n'+'/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@supports not (display: grid) {\n .base-grid,\n distill-header,\n d-title,\n d-abstract,\n d-article,\n d-appendix,\n distill-appendix,\n d-byline,\n d-footnote-list,\n d-citation-list,\n distill-footer {\n display: block;\n padding: 8px;\n }\n}\n\n.base-grid,\ndistill-header,\nd-title,\nd-abstract,\nd-article,\nd-appendix,\ndistill-appendix,\nd-byline,\nd-footnote-list,\nd-citation-list,\ndistill-footer {\n display: grid;\n justify-items: stretch;\n grid-template-columns: [screen-start] 8px [page-start kicker-start text-start gutter-start middle-start] 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr [text-end page-end gutter-end kicker-end middle-end] 8px [screen-end];\n grid-column-gap: 8px;\n}\n\n.grid {\n display: grid;\n grid-column-gap: 8px;\n}\n\n@media(min-width: 768px) {\n .base-grid,\n distill-header,\n d-title,\n d-abstract,\n d-article,\n d-appendix,\n distill-appendix,\n d-byline,\n d-footnote-list,\n d-citation-list,\n distill-footer {\n grid-template-columns: [screen-start] 1fr [page-start kicker-start middle-start text-start] 45px 45px 45px 45px 45px 45px 45px 45px [ kicker-end text-end gutter-start] 45px [middle-end] 45px [page-end gutter-end] 1fr [screen-end];\n grid-column-gap: 16px;\n }\n\n .grid {\n grid-column-gap: 16px;\n }\n}\n\n@media(min-width: 1000px) {\n .base-grid,\n distill-header,\n d-title,\n d-abstract,\n d-article,\n d-appendix,\n distill-appendix,\n d-byline,\n d-footnote-list,\n d-citation-list,\n distill-footer {\n grid-template-columns: [screen-start] 1fr [page-start kicker-start] 50px [middle-start] 50px [text-start kicker-end] 50px 50px 50px 50px 50px 50px 50px 50px [text-end gutter-start] 50px [middle-end] 50px [page-end gutter-end] 1fr [screen-end];\n grid-column-gap: 16px;\n }\n\n .grid {\n grid-column-gap: 16px;\n }\n}\n\n@media(min-width: 1180px) {\n .base-grid,\n distill-header,\n d-title,\n d-abstract,\n d-article,\n d-appendix,\n distill-appendix,\n d-byline,\n d-footnote-list,\n d-citation-list,\n distill-footer {\n grid-template-columns: [screen-start] 1fr [page-start kicker-start] 60px [middle-start] 60px [text-start kicker-end] 60px 60px 60px 60px 60px 60px 60px 60px [text-end gutter-start] 60px [middle-end] 60px [page-end gutter-end] 1fr [screen-end];\n grid-column-gap: 32px;\n }\n\n .grid {\n grid-column-gap: 32px;\n }\n}\n\n\n\n\n.base-grid {\n grid-column: screen;\n}\n\n/* .l-body,\nd-article > * {\n grid-column: text;\n}\n\n.l-page,\nd-title > *,\nd-figure {\n grid-column: page;\n} */\n\n.l-gutter {\n grid-column: gutter;\n}\n\n.l-text,\n.l-body {\n grid-column: text;\n}\n\n.l-page {\n grid-column: page;\n}\n\n.l-body-outset {\n grid-column: middle;\n}\n\n.l-page-outset {\n grid-column: page;\n}\n\n.l-screen {\n grid-column: screen;\n}\n\n.l-screen-inset {\n grid-column: screen;\n padding-left: 16px;\n padding-left: 16px;\n}\n\n\n/* Aside */\n\nd-article aside {\n grid-column: gutter;\n font-size: 12px;\n line-height: 1.6em;\n color: rgba(0, 0, 0, 0.6)\n}\n\n@media(min-width: 768px) {\n aside {\n grid-column: gutter;\n }\n\n .side {\n grid-column: gutter;\n }\n}\n'+'/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-title {\n padding: 2rem 0 1.5rem;\n contain: layout style;\n overflow-x: hidden;\n}\n\n@media(min-width: 768px) {\n d-title {\n padding: 4rem 0 1.5rem;\n }\n}\n\nd-title h1 {\n grid-column: text;\n font-size: 40px;\n font-weight: 700;\n line-height: 1.1em;\n margin: 0 0 0.5rem;\n}\n\n@media(min-width: 768px) {\n d-title h1 {\n font-size: 50px;\n }\n}\n\nd-title p {\n font-weight: 300;\n font-size: 1.2rem;\n line-height: 1.55em;\n grid-column: text;\n}\n\nd-title .status {\n margin-top: 0px;\n font-size: 12px;\n color: #009688;\n opacity: 0.8;\n grid-column: kicker;\n}\n\nd-title .status span {\n line-height: 1;\n display: inline-block;\n padding: 6px 0;\n border-bottom: 1px solid #80cbc4;\n font-size: 11px;\n text-transform: uppercase;\n}\n'+'/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-byline {\n contain: content;\n overflow: hidden;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n font-size: 0.8rem;\n line-height: 1.8em;\n padding: 1.5rem 0;\n min-height: 1.8em;\n}\n\n\nd-byline .byline {\n grid-template-columns: 1fr 1fr;\n grid-column: text;\n}\n\n@media(min-width: 768px) {\n d-byline .byline {\n grid-template-columns: 1fr 1fr 1fr 1fr;\n }\n}\n\nd-byline .authors-affiliations {\n grid-column-end: span 2;\n grid-template-columns: 1fr 1fr;\n margin-bottom: 1em;\n}\n\n@media(min-width: 768px) {\n d-byline .authors-affiliations {\n margin-bottom: 0;\n }\n}\n\nd-byline h3 {\n font-size: 0.6rem;\n font-weight: 400;\n color: rgba(0, 0, 0, 0.5);\n margin: 0;\n text-transform: uppercase;\n}\n\nd-byline p {\n margin: 0;\n}\n\nd-byline a,\nd-article d-byline a {\n color: rgba(0, 0, 0, 0.8);\n text-decoration: none;\n border-bottom: none;\n}\n\nd-article d-byline a:hover {\n text-decoration: underline;\n border-bottom: none;\n}\n\nd-byline p.author {\n font-weight: 500;\n}\n\nd-byline .affiliations {\n\n}\n'+'/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-article {\n contain: layout style;\n overflow-x: hidden;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n padding-top: 2rem;\n color: rgba(0, 0, 0, 0.8);\n}\n\nd-article > * {\n grid-column: text;\n}\n\n@media(min-width: 768px) {\n d-article {\n font-size: 16px;\n }\n}\n\n@media(min-width: 1024px) {\n d-article {\n font-size: 1.06rem;\n line-height: 1.7em;\n }\n}\n\n\n/* H2 */\n\n\nd-article .marker {\n text-decoration: none;\n border: none;\n counter-reset: section;\n grid-column: kicker;\n line-height: 1.7em;\n}\n\nd-article .marker:hover {\n border: none;\n}\n\nd-article .marker span {\n padding: 0 3px 4px;\n border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n position: relative;\n top: 4px;\n}\n\nd-article .marker:hover span {\n color: rgba(0, 0, 0, 0.7);\n border-bottom: 1px solid rgba(0, 0, 0, 0.7);\n}\n\nd-article h2 {\n font-weight: 600;\n font-size: 24px;\n line-height: 1.25em;\n margin: 2rem 0 1.5rem 0;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n padding-bottom: 1rem;\n}\n\n@media(min-width: 1024px) {\n d-article h2 {\n font-size: 36px;\n }\n}\n\n/* H3 */\n\nd-article h3 {\n font-weight: 700;\n font-size: 18px;\n line-height: 1.4em;\n margin-bottom: 1em;\n margin-top: 2em;\n}\n\n@media(min-width: 1024px) {\n d-article h3 {\n font-size: 20px;\n }\n}\n\n/* H4 */\n\nd-article h4 {\n font-weight: 600;\n text-transform: uppercase;\n font-size: 14px;\n line-height: 1.4em;\n}\n\nd-article a {\n color: inherit;\n}\n\nd-article p,\nd-article ul,\nd-article ol,\nd-article blockquote {\n margin-top: 0;\n margin-bottom: 1em;\n margin-left: 0;\n margin-right: 0;\n}\n\nd-article blockquote {\n border-left: 2px solid rgba(0, 0, 0, 0.2);\n padding-left: 2em;\n font-style: italic;\n color: rgba(0, 0, 0, 0.6);\n}\n\nd-article a {\n border-bottom: 1px solid rgba(0, 0, 0, 0.4);\n text-decoration: none;\n}\n\nd-article a:hover {\n border-bottom: 1px solid rgba(0, 0, 0, 0.8);\n}\n\nd-article .link {\n text-decoration: underline;\n cursor: pointer;\n}\n\nd-article ul,\nd-article ol {\n padding-left: 24px;\n}\n\nd-article li {\n margin-bottom: 1em;\n margin-left: 0;\n padding-left: 0;\n}\n\nd-article li:last-child {\n margin-bottom: 0;\n}\n\nd-article pre {\n font-size: 14px;\n margin-bottom: 20px;\n}\n\nd-article hr {\n grid-column: screen;\n width: 100%;\n border: none;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n margin-top: 60px;\n margin-bottom: 60px;\n}\n\nd-article section {\n margin-top: 60px;\n margin-bottom: 60px;\n}\n\nd-article span.equation-mimic {\n font-family: georgia;\n font-size: 115%;\n font-style: italic;\n}\n\nd-article > d-code,\nd-article section > d-code {\n display: block;\n}\n\nd-article > d-math[block],\nd-article section > d-math[block] {\n display: block;\n}\n\n@media (max-width: 768px) {\n d-article > d-code,\n d-article section > d-code,\n d-article > d-math[block],\n d-article section > d-math[block] {\n overflow-x: scroll;\n -ms-overflow-style: none; // IE 10+\n overflow: -moz-scrollbars-none; // Firefox\n }\n\n d-article > d-code::-webkit-scrollbar,\n d-article section > d-code::-webkit-scrollbar,\n d-article > d-math[block]::-webkit-scrollbar,\n d-article section > d-math[block]::-webkit-scrollbar {\n display: none; // Safari and Chrome\n }\n}\n\nd-article .citation {\n color: #668;\n cursor: pointer;\n}\n\nd-include {\n width: auto;\n display: block;\n}\n\nd-figure {\n contain: layout style;\n}\n\n/* KaTeX */\n\n.katex, .katex-prerendered {\n contain: style;\n display: inline-block;\n}\n\n/* Tables */\n\nd-article table {\n border-collapse: collapse;\n margin-bottom: 1.5rem;\n border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n}\n\nd-article table th {\n border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n}\n\nd-article table td {\n border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\nd-article table tr:last-of-type td {\n border-bottom: none;\n}\n\nd-article table th,\nd-article table td {\n font-size: 15px;\n padding: 2px 8px;\n}\n\nd-article table tbody :first-child td {\n padding-top: 2px;\n}\n'+ni+'/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@media print {\n\n @page {\n size: 8in 11in;\n @bottom-right {\n content: counter(page) " of " counter(pages);\n }\n }\n\n html {\n /* no general margins -- CSS Grid takes care of those */\n }\n\n p, code {\n page-break-inside: avoid;\n }\n\n h2, h3 {\n page-break-after: avoid;\n }\n\n d-header {\n visibility: hidden;\n }\n\n d-footer {\n display: none!important;\n }\n\n}\n',mi=[{name:'WebComponents',support:function(){return'customElements'in window&&'attachShadow'in Element.prototype&&'getRootNode'in Element.prototype&&'content'in document.createElement('template')&&'Promise'in window&&'from'in Array},url:'https://distill.pub/third-party/polyfills/webcomponents-lite.js'},{name:'IntersectionObserver',support:function(){return'IntersectionObserver'in window&&'IntersectionObserverEntry'in window},url:'https://distill.pub/third-party/polyfills/intersection-observer.js'}];class yi{static browserSupportsAllFeatures(){return mi.every((e)=>e.support())}static load(e){const t=function(t){t.loaded=!0,console.info('Runlevel 0: Polyfill has finished loading: '+t.name),yi.neededPolyfills.every((e)=>e.loaded)&&(console.info('Runlevel 0: All required polyfills have finished loading.'),console.info('Runlevel 0->1.'),window.distillRunlevel=1,e())};for(const n of yi.neededPolyfills)g(n,t)}static get neededPolyfills(){return yi._neededPolyfills||(yi._neededPolyfills=mi.filter((e)=>!e.support())),yi._neededPolyfills}}const xi=ti('d-abstract',` + + + +`);class ki extends xi(HTMLElement){}const vi=ti('d-appendix',` + + +`,!1);class wi extends vi(HTMLElement){}const Si=/^\s*$/;class Ci extends HTMLElement{static get is(){return'd-article'}constructor(){super(),new MutationObserver((e)=>{for(const t of e)for(const e of t.addedNodes)switch(e.nodeName){case'#text':{const t=e.nodeValue;if(!Si.test(t)){console.warn('Use of unwrapped text in distill articles is discouraged as it breaks layout! Please wrap any text in a or

    tag. We found the following text: '+t);const n=document.createElement('span');n.innerHTML=e.nodeValue,e.parentNode.insertBefore(n,e),e.parentNode.removeChild(e)}}}}).observe(this,{childList:!0})}}var Ti='undefined'==typeof window?'undefined'==typeof global?'undefined'==typeof self?{}:self:global:window,_i=f(function(e,t){(function(e){function t(){this.months=['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'],this.notKey=[',','{','}',' ','='],this.pos=0,this.input='',this.entries=[],this.currentEntry='',this.setInput=function(e){this.input=e},this.getEntries=function(){return this.entries},this.isWhitespace=function(e){return' '==e||'\r'==e||'\t'==e||'\n'==e},this.match=function(e,t){if((void 0==t||null==t)&&(t=!0),this.skipWhitespace(t),this.input.substring(this.pos,this.pos+e.length)==e)this.pos+=e.length;else throw'Token mismatch, expected '+e+', found '+this.input.substring(this.pos);this.skipWhitespace(t)},this.tryMatch=function(e,t){return(void 0==t||null==t)&&(t=!0),this.skipWhitespace(t),this.input.substring(this.pos,this.pos+e.length)==e},this.matchAt=function(){for(;this.input.length>this.pos&&'@'!=this.input[this.pos];)this.pos++;return!('@'!=this.input[this.pos])},this.skipWhitespace=function(e){for(;this.isWhitespace(this.input[this.pos]);)this.pos++;if('%'==this.input[this.pos]&&!0==e){for(;'\n'!=this.input[this.pos];)this.pos++;this.skipWhitespace(e)}},this.value_braces=function(){var e=0;this.match('{',!1);for(var t=this.pos,n=!1;;){if(!n)if('}'==this.input[this.pos]){if(0=this.input.length-1)throw'Unterminated value';n='\\'==this.input[this.pos]&&!1==n,this.pos++}},this.value_comment=function(){for(var e='',t=0;!(this.tryMatch('}',!1)&&0==t);){if(e+=this.input[this.pos],'{'==this.input[this.pos]&&t++,'}'==this.input[this.pos]&&t--,this.pos>=this.input.length-1)throw'Unterminated value:'+this.input.substring(start);this.pos++}return e},this.value_quotes=function(){this.match('"',!1);for(var e=this.pos,t=!1;;){if(!t){if('"'==this.input[this.pos]){var n=this.pos;return this.match('"',!1),this.input.substring(e,n)}if(this.pos>=this.input.length-1)throw'Unterminated value:'+this.input.substring(e)}t='\\'==this.input[this.pos]&&!1==t,this.pos++}},this.single_value=function(){var e=this.pos;if(this.tryMatch('{'))return this.value_braces();if(this.tryMatch('"'))return this.value_quotes();var t=this.key();if(t.match('^[0-9]+$'))return t;if(0<=this.months.indexOf(t.toLowerCase()))return t.toLowerCase();throw'Value expected:'+this.input.substring(e)+' for key: '+t},this.value=function(){for(var e=[this.single_value()];this.tryMatch('#');)this.match('#'),e.push(this.single_value());return e.join('')},this.key=function(){for(var e=this.pos;;){if(this.pos>=this.input.length)throw'Runaway key';if(0<=this.notKey.indexOf(this.input[this.pos]))return this.input.substring(e,this.pos);this.pos++}},this.key_equals_value=function(){var e=this.key();if(this.tryMatch('=')){this.match('=');var t=this.value();return[e,t]}throw'... = value expected, equals sign missing:'+this.input.substring(this.pos)},this.key_value_list=function(){var e=this.key_equals_value();for(this.currentEntry.entryTags={},this.currentEntry.entryTags[e[0]]=e[1];this.tryMatch(',')&&(this.match(','),!this.tryMatch('}'));)e=this.key_equals_value(),this.currentEntry.entryTags[e[0]]=e[1]},this.entry_body=function(e){this.currentEntry={},this.currentEntry.citationKey=this.key(),this.currentEntry.entryType=e.substring(1),this.match(','),this.key_value_list(),this.entries.push(this.currentEntry)},this.directive=function(){return this.match('@'),'@'+this.key()},this.preamble=function(){this.currentEntry={},this.currentEntry.entryType='PREAMBLE',this.currentEntry.entry=this.value_comment(),this.entries.push(this.currentEntry)},this.comment=function(){this.currentEntry={},this.currentEntry.entryType='COMMENT',this.currentEntry.entry=this.value_comment(),this.entries.push(this.currentEntry)},this.entry=function(e){this.entry_body(e)},this.bibtex=function(){for(;this.matchAt();){var e=this.directive();this.match('{'),'@STRING'==e?this.string():'@PREAMBLE'==e?this.preamble():'@COMMENT'==e?this.comment():this.entry(e),this.match('}')}}}e.toJSON=function(e){var n=new t;return n.setInput(e),n.bibtex(),n.entries},e.toBibtex=function(e){var t='';for(var n in e){if(t+='@'+e[n].entryType,t+='{',e[n].citationKey&&(t+=e[n].citationKey+', '),e[n].entry&&(t+=e[n].entry),e[n].entryTags){var i='';for(var a in e[n].entryTags)0!=i.length&&(i+=', '),i+=a+'= {'+e[n].entryTags[a]+'}';t+=i}t+='}\n\n'}return t}})(t)});class Li extends HTMLElement{static get is(){return'd-bibliography'}constructor(){super();const e=new MutationObserver((e)=>{for(const t of e)('SCRIPT'===t.target.nodeName||'characterData'===t.type)&&this.parseIfPossible()});e.observe(this,{childList:!0,characterData:!0,subtree:!0})}connectedCallback(){requestAnimationFrame(()=>{this.parseIfPossible()})}parseIfPossible(){const e=this.querySelector('script');if(e)if('text/bibtex'==e.type){const t=e.textContent;if(this.bibtex!==t){this.bibtex=t;const e=b(this.bibtex);this.notify(e)}}else if('text/json'==e.type){const t=new Map(JSON.parse(e.textContent));this.notify(t)}else console.warn('Unsupported bibliography script tag type: '+e.type)}notify(e){const t=new CustomEvent('onBibliographyChanged',{detail:e,bubbles:!0});this.dispatchEvent(t)}static get observedAttributes(){return['src']}receivedBibtex(e){const t=b(e.target.response);this.notify(t)}attributeChangedCallback(e,t,n){var i=new XMLHttpRequest;i.onload=(t)=>this.receivedBibtex(t),i.onerror=()=>console.warn(`Could not load Bibtex! (tried ${n})`),i.responseType='text',i.open('GET',n,!0),i.send()}}class Ai extends HTMLElement{static get is(){return'd-byline'}set frontMatter(e){this.innerHTML=y(e)}}const Ei=ti('d-cite',` + + + + +

    + + +
    +`);class Di extends Ei(HTMLElement){connectedCallback(){this.outerSpan=this.root.querySelector('#citation-'),this.innerSpan=this.root.querySelector('.citation-number'),this.hoverBox=this.root.querySelector('d-hover-box'),window.customElements.whenDefined('d-hover-box').then(()=>{this.hoverBox.listen(this)})}static get observedAttributes(){return['key']}attributeChangedCallback(e,t,n){const i=t?'onCiteKeyChanged':'onCiteKeyCreated',a=n.split(','),d={detail:[this,a],bubbles:!0},r=new CustomEvent(i,d);document.dispatchEvent(r)}set key(e){this.setAttribute('key',e)}get key(){return this.getAttribute('key')}get keys(){return this.getAttribute('key').split(',')}set numbers(e){const t=e.map((e)=>{return-1==e?'?':e+1+''}),n='['+t.join(', ')+']';this.innerSpan&&(this.innerSpan.textContent=n)}set entries(e){this.hoverBox&&(this.hoverBox.innerHTML=`
      + ${e.map(l).map((e)=>`
    • ${e}
    • `).join('\n')} +
    `)}}const Mi=` +d-citation-list { + contain: layout style; +} + +d-citation-list .references { + grid-column: text; +} + +d-citation-list .references .title { + font-weight: 500; +} +`;class Oi extends HTMLElement{static get is(){return'd-citation-list'}connectedCallback(){this.hasAttribute('distill-prerendered')||(this.style.display='none')}set citations(e){x(this,e)}}var Ui=f(function(e){var t='undefined'==typeof window?'undefined'!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{}:window,n=function(){var e=/\blang(?:uage)?-(\w+)\b/i,n=0,a=t.Prism={util:{encode:function(e){return e instanceof i?new i(e.type,a.util.encode(e.content),e.alias):'Array'===a.util.type(e)?e.map(a.util.encode):e.replace(/&/g,'&').replace(/e.length)break tokenloop;if(!(y instanceof n)){c.lastIndex=0;var v=c.exec(y),w=1;if(!v&&f&&x!=d.length-1){if(c.lastIndex=i,v=c.exec(e),!v)break;for(var S=v.index+(g?v[1].length:0),C=v.index+v[0].length,T=x,k=i,p=d.length;T=k&&(++x,i=k);if(d[x]instanceof n||d[T-1].greedy)continue;w=T-x,y=e.slice(i,k),v.index-=i}if(v){g&&(h=v[1].length);var S=v.index+h,v=v[0].slice(h),C=S+v.length,_=y.slice(0,S),L=y.slice(C),A=[x,w];_&&A.push(_);var E=new n(o,u?a.tokenize(v,u):v,b,v,f);A.push(E),L&&A.push(L),Array.prototype.splice.apply(d,A)}}}}}return d},hooks:{all:{},add:function(e,t){var n=a.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=a.hooks.all[e];if(n&&n.length)for(var d,r=0;d=n[r++];)d(t)}}},i=a.Token=function(e,t,n,i,a){this.type=e,this.content=t,this.alias=n,this.length=0|(i||'').length,this.greedy=!!a};if(i.stringify=function(e,t,n){if('string'==typeof e)return e;if('Array'===a.util.type(e))return e.map(function(n){return i.stringify(n,t,e)}).join('');var d={type:e.type,content:i.stringify(e.content,t,n),tag:'span',classes:['token',e.type],attributes:{},language:t,parent:n};if('comment'==d.type&&(d.attributes.spellcheck='true'),e.alias){var r='Array'===a.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(d.classes,r)}a.hooks.run('wrap',d);var l=Object.keys(d.attributes).map(function(e){return e+'="'+(d.attributes[e]||'').replace(/"/g,'"')+'"'}).join(' ');return'<'+d.tag+' class="'+d.classes.join(' ')+'"'+(l?' '+l:'')+'>'+d.content+''},!t.document)return t.addEventListener?(t.addEventListener('message',function(e){var n=JSON.parse(e.data),i=n.language,d=n.code,r=n.immediateClose;t.postMessage(a.highlight(d,a.languages[i],i)),r&&t.close()},!1),t.Prism):t.Prism;var d=document.currentScript||[].slice.call(document.getElementsByTagName('script')).pop();return d&&(a.filename=d.src,document.addEventListener&&!d.hasAttribute('data-manual')&&('loading'===document.readyState?document.addEventListener('DOMContentLoaded',a.highlightAll):window.requestAnimationFrame?window.requestAnimationFrame(a.highlightAll):window.setTimeout(a.highlightAll,16))),t.Prism}();e.exports&&(e.exports=n),'undefined'!=typeof Ti&&(Ti.Prism=n),n.languages.markup={comment://,prolog:/<\?[\w\W]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},n.hooks.add('wrap',function(e){'entity'===e.type&&(e.attributes.title=e.content.replace(/&/,'&'))}),n.languages.xml=n.languages.markup,n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,n.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},n.languages.css.atrule.inside.rest=n.util.clone(n.languages.css),n.languages.markup&&(n.languages.insertBefore('markup','tag',{style:{pattern:/()[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:n.languages.css,alias:'language-css'}}),n.languages.insertBefore('inside','attr-value',{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:n.languages.css}},alias:'language-css'}},n.languages.markup.tag)),n.languages.clike={comment:[{pattern:/(^|[^\\])#.*/,lookbehind:!0},{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(true|false)\b/,function:/[a-z\.0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},n.languages.javascript=n.languages.extend('clike',{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,function:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),n.languages.insertBefore('javascript','keyword',{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),n.languages.insertBefore('javascript','string',{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:'punctuation'},rest:n.languages.javascript}},string:/[\s\S]+/}}}),n.languages.markup&&n.languages.insertBefore('markup','tag',{script:{pattern:/()[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:n.languages.javascript,alias:'language-javascript'}}),n.languages.js=n.languages.javascript,function(){'undefined'!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var e={js:'javascript',py:'python',rb:'ruby',ps1:'powershell',psm1:'powershell',sh:'bash',bat:'batch',h:'c',tex:'latex'};Array.prototype.forEach&&Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function(t){for(var i,a=t.getAttribute('data-src'),d=t,r=/\blang(?:uage)?-(?!\*)(\w+)\b/i;d&&!r.test(d.className);)d=d.parentNode;if(d&&(i=(t.className.match(r)||[,''])[1]),!i){var o=(a.match(/\.(\w+)$/)||[,''])[1];i=e[o]||o}var l=document.createElement('code');l.className='language-'+i,t.textContent='',l.textContent='Loading\u2026',t.appendChild(l);var s=new XMLHttpRequest;s.open('GET',a,!0),s.onreadystatechange=function(){4==s.readyState&&(400>s.status&&s.responseText?(l.textContent=s.responseText,n.highlightElement(l)):400<=s.status?l.textContent='\u2716 Error '+s.status+' while fetching file: '+s.statusText:l.textContent='\u2716 Error: File does not exist or is empty')},s.send(null)})},document.addEventListener('DOMContentLoaded',self.Prism.fileHighlight))}()});Prism.languages.python={"triple-quoted-string":{pattern:/"""[\s\S]+?"""|'''[\s\S]+?'''/,alias:'string'},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/("|')(?:\\\\|\\?[^\\\r\n])*?\1/,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,boolean:/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/},Prism.languages.clike={comment:[{pattern:/(^|[^\\])#.*/,lookbehind:!0},{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(true|false)\b/,function:/[a-z\.0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/},function(e){var t={variable:[{pattern:/\$?\(\([\w\W]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\w\W]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:'important'},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,function:{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},boolean:{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var n=t.variable[1].inside;n['function']=e.languages.bash['function'],n.keyword=e.languages.bash.keyword,n.boolean=e.languages.bash.boolean,n.operator=e.languages.bash.operator,n.punctuation=e.languages.bash.punctuation}(Prism),Prism.languages.go=Prism.languages.extend('clike',{keyword:/\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/,boolean:/\b(_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i,string:/("|'|`)(\\?.|\r|\n)*?\1/}),delete Prism.languages.go['class-name'],Prism.languages.markdown=Prism.languages.extend('markup',{}),Prism.languages.insertBefore('markdown','prolog',{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:'punctuation'},code:[{pattern:/^(?: {4}|\t).+/m,alias:'keyword'},{pattern:/``.+?``|`[^`\n]+`/,alias:'keyword'}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:'important',inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:'important',inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:'punctuation'},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:'punctuation'},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:'url'},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold),Prism.languages.julia={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:/"""[\s\S]+?"""|'''[\s\S]+?'''|("|')(\\?.)*?\1/,keyword:/\b(abstract|baremodule|begin|bitstype|break|catch|ccall|const|continue|do|else|elseif|end|export|finally|for|function|global|if|immutable|import|importall|let|local|macro|module|print|println|quote|return|try|type|typealias|using|while)\b/,boolean:/\b(true|false)\b/,number:/\b-?(0[box])?(?:[\da-f]+\.?\d*|\.\d+)(?:[efp][+-]?\d+)?j?\b/i,operator:/\+=?|-=?|\*=?|\/[\/=]?|\\=?|\^=?|%=?|÷=?|!=?=?|&=?|\|[=>]?|\$=?|<(?:<=?|[=:])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥]/,punctuation:/[{}[\];(),.:]/};const Ii=ti('d-code',` + + + + +`);class Ni extends ei(Ii(HTMLElement)){renderContent(){if(this.languageName=this.getAttribute('language'),!this.languageName)return void console.warn('You need to provide a language attribute to your block to let us know how to highlight your code; e.g.:\n zeros = np.zeros(shape).');const e=Ui.languages[this.languageName];if(void 0==e)return void console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}'.`);let t=this.textContent;const n=this.shadowRoot.querySelector('#code-container');if(this.hasAttribute('block')){t=t.replace(/\n/,'');const e=t.match(/\s*/);if(t=t.replace(new RegExp('\n'+e,'g'),'\n'),t=t.trim(),n.parentNode instanceof ShadowRoot){const e=document.createElement('pre');this.shadowRoot.removeChild(n),e.appendChild(n),this.shadowRoot.appendChild(e)}}n.className=`language-${this.languageName}`,n.innerHTML=Ui.highlight(t,e)}}const ji=ti('d-footnote',` + + + +
    + +
    +
    + + + + + +`);class Ri extends ji(HTMLElement){constructor(){super();const e=new MutationObserver(this.notify);e.observe(this,{childList:!0,characterData:!0,subtree:!0})}notify(){const e={detail:this,bubbles:!0},t=new CustomEvent('onFootnoteChanged',e);document.dispatchEvent(t)}connectedCallback(){this.hoverBox=this.root.querySelector('d-hover-box'),window.customElements.whenDefined('d-hover-box').then(()=>{this.hoverBox.listen(this)}),Ri.currentFootnoteId+=1;const e=Ri.currentFootnoteId.toString();this.root.host.id='d-footnote-'+e;const t='dt-fn-hover-box-'+e;this.hoverBox.id=t;const n=this.root.querySelector('#fn-');n.setAttribute('id','fn-'+e),n.setAttribute('data-hover-ref',t),n.textContent=e}}Ri.currentFootnoteId=0;const qi=ti('d-footnote-list',` + + +

    Footnotes

    +
      +`,!1);class Fi extends qi(HTMLElement){connectedCallback(){super.connectedCallback(),this.list=this.root.querySelector('ol'),this.root.style.display='none'}set footnotes(e){if(this.list.innerHTML='',e.length){this.root.style.display='';for(const t of e){const e=document.createElement('li');e.id=t.id+'-listing',e.innerHTML=t.innerHTML;const n=document.createElement('a');n.setAttribute('class','footnote-backlink'),n.textContent='[\u21A9]',n.href='#'+t.id,e.appendChild(n),this.list.appendChild(e)}}else this.root.style.display='none'}}const Pi=ti('d-hover-box',` + + +
      +
      + +
      +
      +`);class Hi extends Pi(HTMLElement){constructor(){super()}connectedCallback(){}listen(e){this.bindDivEvents(this),this.bindTriggerEvents(e)}bindDivEvents(e){e.addEventListener('mouseover',()=>{this.visible||this.showAtNode(e),this.stopTimeout()}),e.addEventListener('mouseout',()=>{this.extendTimeout(500)}),e.addEventListener('touchstart',(e)=>{e.stopPropagation()},{passive:!0}),document.body.addEventListener('touchstart',()=>{this.hide()},{passive:!0})}bindTriggerEvents(e){e.addEventListener('mouseover',()=>{this.visible||this.showAtNode(e),this.stopTimeout()}),e.addEventListener('mouseout',()=>{this.extendTimeout(300)}),e.addEventListener('touchstart',(t)=>{this.visible?this.hide():this.showAtNode(e),t.stopPropagation()},{passive:!0})}show(e){this.visible=!0,this.style.display='block',this.style.top=Pn(e[1]+10)+'px'}showAtNode(e){const t=e.getBoundingClientRect();this.show([e.offsetLeft+t.width,e.offsetTop+t.height])}hide(){this.visible=!1,this.style.display='none',this.stopTimeout()}stopTimeout(){this.timeout&&clearTimeout(this.timeout)}extendTimeout(e){this.stopTimeout(),this.timeout=setTimeout(()=>{this.hide()},e)}}class zi extends HTMLElement{static get is(){return'd-title'}}const Yi=ti('d-references',` + +`,!1);class Bi extends Yi(HTMLElement){}class Wi extends HTMLElement{static get is(){return'd-toc'}connectedCallback(){this.getAttribute('prerendered')||(window.onload=()=>{const e=document.querySelector('d-article'),t=e.querySelectorAll('h2, h3');k(this,t)})}}class Vi extends HTMLElement{static get is(){return'd-figure'}static get readyQueue(){return Vi._readyQueue||(Vi._readyQueue=[]),Vi._readyQueue}static addToReadyQueue(e){-1===Vi.readyQueue.indexOf(e)&&(Vi.readyQueue.push(e),Vi.runReadyQueue())}static runReadyQueue(){const e=Vi.readyQueue.sort((e,t)=>e._seenOnScreen-t._seenOnScreen).filter((e)=>!e._ready).pop();e&&(e.ready(),requestAnimationFrame(Vi.runReadyQueue))}constructor(){super(),this._ready=!1,this._onscreen=!1,this._offscreen=!0}connectedCallback(){this.loadsWhileScrolling=this.hasAttribute('loadsWhileScrolling'),Vi.marginObserver.observe(this),Vi.directObserver.observe(this)}disconnectedCallback(){Vi.marginObserver.unobserve(this),Vi.directObserver.unobserve(this)}static get marginObserver(){if(!Vi._marginObserver){const e=window.innerHeight,t=Fn(2*e),n=Vi.didObserveMarginIntersection,i=new IntersectionObserver(n,{rootMargin:t+'px 0px '+t+'px 0px',threshold:0.01});Vi._marginObserver=i}return Vi._marginObserver}static didObserveMarginIntersection(e){for(const t of e){const e=t.target;t.isIntersecting&&!e._ready&&Vi.addToReadyQueue(e)}}static get directObserver(){return Vi._directObserver||(Vi._directObserver=new IntersectionObserver(Vi.didObserveDirectIntersection,{rootMargin:'0px',threshold:[0,1]})),Vi._directObserver}static didObserveDirectIntersection(e){for(const t of e){const e=t.target;t.isIntersecting?(e._seenOnScreen=new Date,e._offscreen&&e.onscreen()):e._onscreen&&e.offscreen()}}addEventListener(e,t){super.addEventListener(e,t),'ready'===e&&-1!==Vi.readyQueue.indexOf(this)&&(this._ready=!1,Vi.runReadyQueue()),'onscreen'===e&&this.onscreen()}ready(){this._ready=!0,Vi.marginObserver.unobserve(this);const e=new CustomEvent('ready');this.dispatchEvent(e)}onscreen(){this._onscreen=!0,this._offscreen=!1;const e=new CustomEvent('onscreen');this.dispatchEvent(e)}offscreen(){this._onscreen=!1,this._offscreen=!0;const e=new CustomEvent('offscreen');this.dispatchEvent(e)}}if('undefined'!=typeof window){Vi.isScrolling=!1;let e;window.addEventListener('scroll',()=>{Vi.isScrolling=!0,clearTimeout(e),e=setTimeout(()=>{Vi.isScrolling=!1,Vi.runReadyQueue()},500)},!0)}const Ki=ti('d-interstitial',` + + +
      +
      +

      This article is in review.

      +

      Do not share this URL or the contents of this article. Thank you!

      + +

      Enter the password we shared with you as part of the review process to view the article.

      +
      +
      +`);class $i extends Ki(HTMLElement){connectedCallback(){if(this.shouldRemoveSelf())this.parentElement.removeChild(this);else{const e=this.root.querySelector('#interstitial-password-input');e.oninput=(e)=>this.passwordChanged(e)}}passwordChanged(e){const t=e.target.value;t===this.password&&(console.log('Correct password entered.'),this.parentElement.removeChild(this),'undefined'!=typeof Storage&&(console.log('Saved that correct password was entered.'),localStorage.setItem(this.localStorageIdentifier(),'true')))}shouldRemoveSelf(){return window&&window.location.hostname==='distill.pub'?(console.warn('Interstitial found on production, hiding it.'),!0):'undefined'!=typeof Storage&&'true'===localStorage.getItem(this.localStorageIdentifier())&&(console.log('Loaded that correct password was entered before; skipping interstitial.'),!0)}localStorageIdentifier(){return'distill-drafts'+(window?window.location.pathname:'-')+'interstitial-password-correct'}}var Xi=function(e,t){return et?1:e>=t?0:NaN},Ji=function(e){return 1===e.length&&(e=v(e)),{left:function(t,n,i,a){for(null==i&&(i=0),null==a&&(a=t.length);i>>1;0>e(t[d],n)?i=d+1:a=d}return i},right:function(t,n,i,a){for(null==i&&(i=0),null==a&&(a=t.length);i>>1;0(i=arguments.length)?(t=e,e=0,1):3>i?1:+a;for(var d=-1,i=0|Rn(0,qn((t-e)/a)),n=Array(i);++d=this.r&&0<=this.g&&255>=this.g&&0<=this.b&&255>=this.b&&0<=this.opacity&&1>=this.opacity},toString:function(){var e=this.opacity;return e=isNaN(e)?1:Rn(0,Hn(1,e)),(1===e?'rgb(':'rgba(')+Rn(0,Hn(255,Pn(this.r)||0))+', '+Rn(0,Hn(255,Pn(this.g)||0))+', '+Rn(0,Hn(255,Pn(this.b)||0))+(1===e?')':', '+e+')')}})),ra(F,function(e,t,n,i){return 1===arguments.length?q(e):new F(e,t,n,null==i?1:i)},_(L,{brighter:function(e){return e=null==e?la:In(la,e),new F(this.h,this.s,this.l*e,this.opacity)},darker:function(e){return e=null==e?oa:In(oa,e),new F(this.h,this.s,this.l*e,this.opacity)},rgb:function(){var e=this.h%360+360*(0>this.h),t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,i=n+(0.5>n?n:1-n)*t,a=2*n-i;return new j(P(240<=e?e-240:e+120,a,i),P(e,a,i),P(120>e?e+240:e-120,a,i),this.opacity)},displayable:function(){return(0<=this.s&&1>=this.s||isNaN(this.s))&&0<=this.l&&1>=this.l&&0<=this.opacity&&1>=this.opacity}}));var ya=On/180,xa=180/On,ka=18,Kn=0.95047,Xn=1,Yn=1.08883,Zn=4/29,va=6/29,wa=3*va*va,Sa=va*va*va;ra(Y,function(e,t,n,i){return 1===arguments.length?H(e):new Y(e,t,n,null==i?1:i)},_(L,{brighter:function(e){return new Y(this.l+ka*(null==e?1:e),this.a,this.b,this.opacity)},darker:function(e){return new Y(this.l-ka*(null==e?1:e),this.a,this.b,this.opacity)},rgb:function(){var e=(this.l+16)/116,t=isNaN(this.a)?e:e+this.a/500,n=isNaN(this.b)?e:e-this.b/200;return e=Xn*V(e),t=Kn*V(t),n=Yn*V(n),new j(K(3.2404542*t-1.5371385*e-0.4985314*n),K(-0.969266*t+1.8760108*e+0.041556*n),K(0.0556434*t-0.2040259*e+1.0572252*n),this.opacity)}})),ra(X,function(e,t,n,i){return 1===arguments.length?z(e):new X(e,t,n,null==i?1:i)},_(L,{brighter:function(e){return new X(this.h,this.c,this.l+ka*(null==e?1:e),this.opacity)},darker:function(e){return new X(this.h,this.c,this.l-ka*(null==e?1:e),this.opacity)},rgb:function(){return H(this).rgb()}}));var Ca=-0.14861,A=+1.78277,B=-0.29227,C=-0.90649,D=+1.97294,E=D*C,Ta=D*A,_a=A*B-C*Ca;ra(Z,Q,_(L,{brighter:function(e){return e=null==e?la:In(la,e),new Z(this.h,this.s,this.l*e,this.opacity)},darker:function(e){return e=null==e?oa:In(oa,e),new Z(this.h,this.s,this.l*e,this.opacity)},rgb:function(){var e=isNaN(this.h)?0:(this.h+120)*ya,t=+this.l,n=isNaN(this.s)?0:this.s*t*(1-t),i=Mn(e),a=Dn(e);return new j(255*(t+n*(Ca*i+A*a)),255*(t+n*(B*i+C*a)),255*(t+n*(D*i)),this.opacity)}}));var La=function(e){return function(){return e}},Aa=function e(t){function n(e,t){var n=i((e=N(e)).r,(t=N(t)).r),a=i(e.g,t.g),d=i(e.b,t.b),r=ne(e.opacity,t.opacity);return function(i){return e.r=n(i),e.g=a(i),e.b=d(i),e.opacity=r(i),e+''}}var i=te(t);return n.gamma=e,n}(1),Ea=function(e,t){var n,i=t?t.length:0,a=e?Hn(i,e.length):0,d=Array(i),r=Array(i);for(n=0;nr&&(d=n.slice(r,d),l[o]?l[o]+=d:l[++o]=d),(t=t[0])===(a=a[0])?l[o]?l[o]+=a:l[++o]=a:(l[++o]=null,s.push({i:o,x:Ma(t,a)})),r=Ia.lastIndex;return rl.length?s[0]?ae(s[0].x):ie(n):(n=s.length,function(e){for(var t,a=0;an?n-360*Pn(n/360):n):La(isNaN(e)?t:e)});var qa,Fa=de(ne),Pa=function(e){return function(){return e}},Ha=function(e){return+e},za=[0,1],Ya=function(e,t){if(0>(n=(e=t?e.toExponential(t-1):e.toExponential()).indexOf('e')))return null;var n,i=e.slice(0,n);return[1d&&(o=Rn(1,d-l)),i.push(a.substring(r-=o,r+o)),!((l+=o+1)>d));)o=e[t=(t+1)%e.length];return i.reverse().join(n)}},Va=function(e){return function(t){return t.replace(/[0-9]/g,function(t){return e[+t]})}},Ka=function(e,t){var n=Ya(e,t);if(!n)return e+'';var i=n[0],a=n[1];return 0>a?'0.'+Array(-a).join('0')+i:i.length>a+1?i.slice(0,a+1)+'.'+i.slice(a+1):i+Array(a-i.length+2).join('0')},$a={"":function(e,t){e=e.toPrecision(t);out:for(var a,d=e.length,n=1,i=-1;ni?r+Array(l-i+1).join('0'):0=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;fe.prototype=he.prototype,he.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?'0':'')+(null==this.width?'':Rn(1,0|this.width))+(this.comma?',':'')+(null==this.precision?'':'.'+Rn(0,0|this.precision))+this.type};var re,Ja,Qa,Za=function(e){return e},Ga=['y','z','a','f','p','n','\xB5','m','','k','M','G','T','P','E','Z','Y'],ed=function(e){function t(e){function t(e){var t,i,n,c=b,k=m;if('c'===h)k=y(e)+k,e='';else{e=+e;var v=0>e;if(e=y(Un(e),f),v&&0==+e&&(v=!1),c=(v?'('===s?s:'-':'-'===s||'('===s?'':s)+c,k=k+('s'===h?Ga[8+qa/3]:'')+(v&&'('===s?')':''),x)for(t=-1,i=e.length;++tn||57>1)+c+e+k+S.slice(w);break;default:e=S+c+e+k;}return r(e)}e=fe(e);var o=e.fill,l=e.align,s=e.sign,c=e.symbol,u=e.zero,p=e.width,g=e.comma,f=e.precision,h=e.type,b='$'===c?n[0]:'#'===c&&/[boxX]/.test(h)?'0'+h.toLowerCase():'',m='$'===c?n[1]:/[%p]/.test(h)?i:'',y=$a[h],x=!h||/[defgprs%]/.test(h);return f=null==f?h?6:12:/[gprs]/.test(h)?Rn(1,Hn(21,f)):Rn(0,Hn(20,f)),t.toString=function(){return e+''},t}var a=e.grouping&&e.thousands?Wa(e.grouping,e.thousands):Za,n=e.currency,d=e.decimal,r=e.numerals?Va(e.numerals):Za,i=e.percent||'%';return{format:t,formatPrefix:function(n,i){var a=t((n=fe(n),n.type='f',n)),d=3*Rn(-8,Hn(8,Fn(Ba(i)/3))),r=In(10,-d),o=Ga[8+d/3];return function(e){return a(r*e)+o}}}};(function(e){return re=ed(e),Ja=re.format,Qa=re.formatPrefix,re})({decimal:'.',thousands:',',grouping:[3],currency:['$','']});var td=function(e){return Rn(0,-Ba(Un(e)))},nd=function(e,t){return Rn(0,3*Rn(-8,Hn(8,Fn(Ba(t)/3)))-Ba(Un(e)))},id=function(e,t){return e=Un(e),t=Un(t)-e,Rn(0,Ba(t)-Ba(e))+1},ad=function(e,t,n){var i,a=e[0],d=e[e.length-1],r=S(a,d,null==t?10:t);switch(n=fe(null==n?',f':n),n.type){case's':{var o=Rn(Un(a),Un(d));return null!=n.precision||isNaN(i=nd(r,o))||(n.precision=i),Qa(n,o)}case'':case'e':case'g':case'p':case'r':{null!=n.precision||isNaN(i=id(r,Rn(Un(a),Un(d))))||(n.precision=i-('e'===n.type));break}case'f':case'%':{null!=n.precision||isNaN(i=td(r))||(n.precision=i-2*('%'===n.type));break}}return Ja(n)},dd=new Date,rd=new Date,od=ye(function(){},function(e,t){e.setTime(+e+t)},function(e,t){return t-e});od.every=function(e){return e=Fn(e),isFinite(e)&&0t&&(t+=cd),e.setTime(Fn((+e-t)/cd)*cd+t)},function(e,t){e.setTime(+e+t*cd)},function(e,t){return(t-e)/cd},function(e){return e.getHours()}),bd=ye(function(e){e.setHours(0,0,0,0)},function(e,t){e.setDate(e.getDate()+t)},function(e,t){return(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*sd)/ud},function(e){return e.getDate()-1}),md=xe(0),yd=xe(1),xd=xe(2),kd=xe(3),vd=xe(4),wd=xe(5),Sd=xe(6),Cd=ye(function(e){e.setDate(1),e.setHours(0,0,0,0)},function(e,t){e.setMonth(e.getMonth()+t)},function(e,t){return t.getMonth()-e.getMonth()+12*(t.getFullYear()-e.getFullYear())},function(e){return e.getMonth()}),Td=ye(function(e){e.setMonth(0,1),e.setHours(0,0,0,0)},function(e,t){e.setFullYear(e.getFullYear()+t)},function(e,t){return t.getFullYear()-e.getFullYear()},function(e){return e.getFullYear()});Td.every=function(e){return isFinite(e=Fn(e))&&0arguments.length){for(;++ot&&(this._names.push(e),this._node.setAttribute('class',this._names.join(' ')))},remove:function(e){var t=this._names.indexOf(e);0<=t&&(this._names.splice(t,1),this._node.setAttribute('class',this._names.join(' ')))},contains:function(e){return 0<=this._names.indexOf(e)}};var wr=[null];xn.prototype=function(){return new xn([[document.documentElement]],wr)}.prototype={constructor:xn,select:function(e){'function'!=typeof e&&(e=br(e));for(var t=this._groups,a=t.length,d=Array(a),r=0;r=v&&(v=k+1);!(x=b[v])&&++varguments.length){var i=this.node();return n.local?i.getAttributeNS(n.space,n.local):i.getAttribute(n)}return this.each((null==t?n.local?Ft:qt:'function'==typeof t?n.local?Yt:zt:n.local?Ht:Pt)(n,t))},style:function(e,t,n){return 1arguments.length){for(var d=Zt(this.node()),r=-1,i=a.length;++rarguments.length){var n=this.node().__on;if(n)for(var s,o=0,c=n.length;oarguments.length&&(a=t,t=gr().changedTouches);for(var d,r=0,i=t?t.length:0;rx}b.mouse('drag')}function i(){Sr(ur.view).on('mousemove.drag mouseup.drag',null),vn(ur.view,c),Tr(),b.mouse('end')}function a(){if(p.apply(this,arguments)){var e,t,i=ur.changedTouches,a=g.apply(this,arguments),d=i.length;for(e=0;e + :host { + position: relative; + display: inline-block; + } + + :host(:focus) { + outline: none; + } + + .background { + padding: 9px 0; + color: white; + position: relative; + } + + .track { + height: 3px; + width: 100%; + border-radius: 2px; + background-color: hsla(0, 0%, 0%, 0.2); + } + + .track-fill { + position: absolute; + top: 9px; + height: 3px; + border-radius: 4px; + background-color: hsl(24, 100%, 50%); + } + + .knob-container { + position: absolute; + top: 10px; + } + + .knob { + position: absolute; + top: -6px; + left: -6px; + width: 13px; + height: 13px; + background-color: hsl(24, 100%, 50%); + border-radius: 50%; + transition-property: transform; + transition-duration: 0.18s; + transition-timing-function: ease; + } + .mousedown .knob { + transform: scale(1.5); + } + + .knob-highlight { + position: absolute; + top: -6px; + left: -6px; + width: 13px; + height: 13px; + background-color: hsla(0, 0%, 0%, 0.1); + border-radius: 50%; + transition-property: transform; + transition-duration: 0.18s; + transition-timing-function: ease; + } + + .focus .knob-highlight { + transform: scale(2); + } + + .ticks { + position: absolute; + top: 16px; + height: 4px; + width: 100%; + z-index: -1; + } + + .ticks .tick { + position: absolute; + height: 100%; + border-left: 1px solid hsla(0, 0%, 0%, 0.2); + } + + + +
      +
      +
      +
      +
      +
      +
      +
      +
      +`),Dr={left:37,up:38,right:39,down:40,pageUp:33,pageDown:34,end:35,home:36};class Mr extends Er(HTMLElement){connectedCallback(){this.connected=!0,this.setAttribute('role','slider'),this.hasAttribute('tabindex')||this.setAttribute('tabindex',0),this.mouseEvent=!1,this.knob=this.root.querySelector('.knob-container'),this.background=this.root.querySelector('.background'),this.trackFill=this.root.querySelector('.track-fill'),this.track=this.root.querySelector('.track'),this.min=this.min?this.min:0,this.max=this.max?this.max:100,this.scale=me().domain([this.min,this.max]).range([0,1]).clamp(!0),this.origin=this.origin===void 0?this.min:this.origin,this.step=this.step?this.step:1,this.update(this.value?this.value:0),this.ticks=!!this.ticks&&this.ticks,this.renderTicks(),this.drag=Ar().container(this.background).on('start',()=>{this.mouseEvent=!0,this.background.classList.add('mousedown'),this.changeValue=this.value,this.dragUpdate()}).on('drag',()=>{this.dragUpdate()}).on('end',()=>{this.mouseEvent=!1,this.background.classList.remove('mousedown'),this.dragUpdate(),this.changeValue!==this.value&&this.dispatchChange(),this.changeValue=this.value}),this.drag(Sr(this.background)),this.addEventListener('focusin',()=>{this.mouseEvent||this.background.classList.add('focus')}),this.addEventListener('focusout',()=>{this.background.classList.remove('focus')}),this.addEventListener('keydown',this.onKeyDown)}static get observedAttributes(){return['min','max','value','step','ticks','origin','tickValues','tickLabels']}attributeChangedCallback(e,t,n){isNaN(n)||void 0===n||null===n||('min'==e&&(this.min=+n,this.setAttribute('aria-valuemin',this.min)),'max'==e&&(this.max=+n,this.setAttribute('aria-valuemax',this.max)),'value'==e&&this.update(+n),'origin'==e&&(this.origin=+n),'step'==e&&0{const n=document.createElement('div');n.classList.add('tick'),n.style.left=100*this.scale(t)+'%',e.appendChild(n)})}else e.style.display='none'}}var Or='\n \n\n';const Ur=ti('distill-header',` + + +`,!1);class Ir extends Ur(HTMLElement){}const Nr=` + +`;class jr extends HTMLElement{static get is(){return'distill-appendix'}set frontMatter(e){this.innerHTML=Ln(e)}}const Rr=ti('distill-footer',` + + +
      + + is dedicated to clear explanations of machine learning + + + +
      + +`);class qr extends Rr(HTMLElement){}const Fr=function(){if(1>window.distillRunlevel)throw new Error('Insufficient Runlevel for Distill Template!');if('distillTemplateIsLoading'in window&&window.distillTemplateIsLoading)throw new Error('Runlevel 1: Distill Template is getting loaded more than once, aborting!');else window.distillTemplateIsLoading=!0,console.info('Runlevel 1: Distill Template has started loading.');p(document),console.info('Runlevel 1: Static Distill styles have been added.'),console.info('Runlevel 1->2.'),window.distillRunlevel+=1;for(const[e,t]of Object.entries(hi.listeners))'function'==typeof t?document.addEventListener(e,t):console.error('Runlevel 2: Controller listeners need to be functions!');console.info('Runlevel 2: We can now listen to controller events.'),console.info('Runlevel 2->3.'),window.distillRunlevel+=1;if(2>window.distillRunlevel)throw new Error('Insufficient Runlevel for adding custom elements!');const e=[ki,wi,Ci,Li,Ai,Di,Oi,Ni,Ri,Fi,pi,Hi,zi,T,Bi,Wi,Vi,Mr,$i].concat([Ir,jr,qr]);for(const t of e)console.info('Runlevel 2: Registering custom element: '+t.is),customElements.define(t.is,t);console.info('Runlevel 3: Distill Template finished registering custom elements.'),console.info('Runlevel 3->4.'),window.distillRunlevel+=1,hi.listeners.DOMContentLoaded(),console.info('Runlevel 4: Distill Template initialisation complete.')};window.distillRunlevel=0,yi.browserSupportsAllFeatures()?(console.info('Runlevel 0: No need for polyfills.'),console.info('Runlevel 0->1.'),window.distillRunlevel+=1,Fr()):(console.info('Runlevel 0: Distill Template is loading polyfills.'),yi.load(Fr))}); +//# sourceMappingURL=template.v2.js.map +} diff --git a/docs/site_libs/font-awesome-5.1.0/css/all.css b/docs/site_libs/font-awesome-5.1.0/css/all.css new file mode 100644 index 00000000..7fec2e37 --- /dev/null +++ b/docs/site_libs/font-awesome-5.1.0/css/all.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:a 2s infinite linear}.fa-pulse{animation:a 1s infinite steps(8)}@keyframes a{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-balance-scale:before{content:"\f24e"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bicycle:before{content:"\f206"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blind:before{content:"\f29d"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-open:before{content:"\f518"}.fa-bookmark:before{content:"\f02e"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-certificate:before{content:"\f0a3"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-concierge-bell:before{content:"\f562"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-credit-card:before{content:"\f09d"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-deviantart:before{content:"\f1bd"}.fa-diagnoses:before{content:"\f470"}.fa-dice:before{content:"\f522"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-gift:before{content:"\f06b"}.fa-git:before{content:"\f1d3"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hashtag:before{content:"\f292"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-houzz:before{content:"\f27c"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-internet-explorer:before{content:"\f26b"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mercury:before{content:"\f223"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-motorcycle:before{content:"\f21c"}.fa-mouse-pointer:before{content:"\f245"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-nintendo-switch:before{content:"\f418"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-old-republic:before{content:"\f510"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-people-carry:before{content:"\f4ce"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-volume:before{content:"\f2a0"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poo:before{content:"\f2fe"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-r-project:before{content:"\f4f7"}.fa-random:before{content:"\f074"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-rendact:before{content:"\f3e4"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-retweet:before{content:"\f079"}.fa-ribbon:before{content:"\f4d6"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-sass:before{content:"\f41e"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-search:before{content:"\f002"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skull:before{content:"\f54c"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowflake:before{content:"\f2dc"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toolbox:before{content:"\f552"}.fa-tooth:before{content:"\f5c9"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-train:before{content:"\f238"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-moving:before{content:"\f4df"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/docs/site_libs/font-awesome-5.1.0/css/v4-shims.css b/docs/site_libs/font-awesome-5.1.0/css/v4-shims.css new file mode 100644 index 00000000..b10f6554 --- /dev/null +++ b/docs/site_libs/font-awesome-5.1.0/css/v4-shims.css @@ -0,0 +1,2170 @@ +/*! + * Font Awesome Free 5.1.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa.fa-glass:before { + content: "\f000"; } + +.fa.fa-meetup { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-star-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-o:before { + content: "\f005"; } + +.fa.fa-remove:before { + content: "\f00d"; } + +.fa.fa-close:before { + content: "\f00d"; } + +.fa.fa-gear:before { + content: "\f013"; } + +.fa.fa-trash-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-trash-o:before { + content: "\f2ed"; } + +.fa.fa-file-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-o:before { + content: "\f15b"; } + +.fa.fa-clock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-clock-o:before { + content: "\f017"; } + +.fa.fa-arrow-circle-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-down:before { + content: "\f358"; } + +.fa.fa-arrow-circle-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-up:before { + content: "\f35b"; } + +.fa.fa-play-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-play-circle-o:before { + content: "\f144"; } + +.fa.fa-repeat:before { + content: "\f01e"; } + +.fa.fa-rotate-right:before { + content: "\f01e"; } + +.fa.fa-refresh:before { + content: "\f021"; } + +.fa.fa-list-alt { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-dedent:before { + content: "\f03b"; } + +.fa.fa-video-camera:before { + content: "\f03d"; } + +.fa.fa-picture-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-picture-o:before { + content: "\f03e"; } + +.fa.fa-photo { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-photo:before { + content: "\f03e"; } + +.fa.fa-image { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-image:before { + content: "\f03e"; } + +.fa.fa-pencil:before { + content: "\f303"; } + +.fa.fa-map-marker:before { + content: "\f3c5"; } + +.fa.fa-pencil-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-pencil-square-o:before { + content: "\f044"; } + +.fa.fa-share-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-share-square-o:before { + content: "\f14d"; } + +.fa.fa-check-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-check-square-o:before { + content: "\f14a"; } + +.fa.fa-arrows:before { + content: "\f0b2"; } + +.fa.fa-times-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-circle-o:before { + content: "\f057"; } + +.fa.fa-check-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-check-circle-o:before { + content: "\f058"; } + +.fa.fa-mail-forward:before { + content: "\f064"; } + +.fa.fa-eye { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-eye-slash { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-warning:before { + content: "\f071"; } + +.fa.fa-calendar:before { + content: "\f073"; } + +.fa.fa-arrows-v:before { + content: "\f338"; } + +.fa.fa-arrows-h:before { + content: "\f337"; } + +.fa.fa-bar-chart { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bar-chart:before { + content: "\f080"; } + +.fa.fa-bar-chart-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bar-chart-o:before { + content: "\f080"; } + +.fa.fa-twitter-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gears:before { + content: "\f085"; } + +.fa.fa-thumbs-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-up:before { + content: "\f164"; } + +.fa.fa-thumbs-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-down:before { + content: "\f165"; } + +.fa.fa-heart-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-heart-o:before { + content: "\f004"; } + +.fa.fa-sign-out:before { + content: "\f2f5"; } + +.fa.fa-linkedin-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linkedin-square:before { + content: "\f08c"; } + +.fa.fa-thumb-tack:before { + content: "\f08d"; } + +.fa.fa-external-link:before { + content: "\f35d"; } + +.fa.fa-sign-in:before { + content: "\f2f6"; } + +.fa.fa-github-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-lemon-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-lemon-o:before { + content: "\f094"; } + +.fa.fa-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-square-o:before { + content: "\f0c8"; } + +.fa.fa-bookmark-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bookmark-o:before { + content: "\f02e"; } + +.fa.fa-twitter { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook:before { + content: "\f39e"; } + +.fa.fa-facebook-f { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-f:before { + content: "\f39e"; } + +.fa.fa-github { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-credit-card { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-feed:before { + content: "\f09e"; } + +.fa.fa-hdd-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hdd-o:before { + content: "\f0a0"; } + +.fa.fa-hand-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-right:before { + content: "\f0a4"; } + +.fa.fa-hand-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-left:before { + content: "\f0a5"; } + +.fa.fa-hand-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-up:before { + content: "\f0a6"; } + +.fa.fa-hand-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-down:before { + content: "\f0a7"; } + +.fa.fa-arrows-alt:before { + content: "\f31e"; } + +.fa.fa-group:before { + content: "\f0c0"; } + +.fa.fa-chain:before { + content: "\f0c1"; } + +.fa.fa-scissors:before { + content: "\f0c4"; } + +.fa.fa-files-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-files-o:before { + content: "\f0c5"; } + +.fa.fa-floppy-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-floppy-o:before { + content: "\f0c7"; } + +.fa.fa-navicon:before { + content: "\f0c9"; } + +.fa.fa-reorder:before { + content: "\f0c9"; } + +.fa.fa-pinterest { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pinterest-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus:before { + content: "\f0d5"; } + +.fa.fa-money { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-money:before { + content: "\f3d1"; } + +.fa.fa-unsorted:before { + content: "\f0dc"; } + +.fa.fa-sort-desc:before { + content: "\f0dd"; } + +.fa.fa-sort-asc:before { + content: "\f0de"; } + +.fa.fa-linkedin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linkedin:before { + content: "\f0e1"; } + +.fa.fa-rotate-left:before { + content: "\f0e2"; } + +.fa.fa-legal:before { + content: "\f0e3"; } + +.fa.fa-tachometer:before { + content: "\f3fd"; } + +.fa.fa-dashboard:before { + content: "\f3fd"; } + +.fa.fa-comment-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-comment-o:before { + content: "\f075"; } + +.fa.fa-comments-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-comments-o:before { + content: "\f086"; } + +.fa.fa-flash:before { + content: "\f0e7"; } + +.fa.fa-clipboard { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paste { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paste:before { + content: "\f328"; } + +.fa.fa-lightbulb-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-lightbulb-o:before { + content: "\f0eb"; } + +.fa.fa-exchange:before { + content: "\f362"; } + +.fa.fa-cloud-download:before { + content: "\f381"; } + +.fa.fa-cloud-upload:before { + content: "\f382"; } + +.fa.fa-bell-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bell-o:before { + content: "\f0f3"; } + +.fa.fa-cutlery:before { + content: "\f2e7"; } + +.fa.fa-file-text-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-text-o:before { + content: "\f15c"; } + +.fa.fa-building-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-building-o:before { + content: "\f1ad"; } + +.fa.fa-hospital-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hospital-o:before { + content: "\f0f8"; } + +.fa.fa-tablet:before { + content: "\f3fa"; } + +.fa.fa-mobile:before { + content: "\f3cd"; } + +.fa.fa-mobile-phone:before { + content: "\f3cd"; } + +.fa.fa-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-circle-o:before { + content: "\f111"; } + +.fa.fa-mail-reply:before { + content: "\f3e5"; } + +.fa.fa-github-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-folder-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-folder-o:before { + content: "\f07b"; } + +.fa.fa-folder-open-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-folder-open-o:before { + content: "\f07c"; } + +.fa.fa-smile-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-smile-o:before { + content: "\f118"; } + +.fa.fa-frown-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-frown-o:before { + content: "\f119"; } + +.fa.fa-meh-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-meh-o:before { + content: "\f11a"; } + +.fa.fa-keyboard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-keyboard-o:before { + content: "\f11c"; } + +.fa.fa-flag-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-flag-o:before { + content: "\f024"; } + +.fa.fa-mail-reply-all:before { + content: "\f122"; } + +.fa.fa-star-half-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-o:before { + content: "\f089"; } + +.fa.fa-star-half-empty { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-empty:before { + content: "\f089"; } + +.fa.fa-star-half-full { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-full:before { + content: "\f089"; } + +.fa.fa-code-fork:before { + content: "\f126"; } + +.fa.fa-chain-broken:before { + content: "\f127"; } + +.fa.fa-shield:before { + content: "\f3ed"; } + +.fa.fa-calendar-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-o:before { + content: "\f133"; } + +.fa.fa-maxcdn { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-html5 { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-css3 { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ticket:before { + content: "\f3ff"; } + +.fa.fa-minus-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-minus-square-o:before { + content: "\f146"; } + +.fa.fa-level-up:before { + content: "\f3bf"; } + +.fa.fa-level-down:before { + content: "\f3be"; } + +.fa.fa-pencil-square:before { + content: "\f14b"; } + +.fa.fa-external-link-square:before { + content: "\f360"; } + +.fa.fa-compass { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down:before { + content: "\f150"; } + +.fa.fa-toggle-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-down:before { + content: "\f150"; } + +.fa.fa-caret-square-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-up:before { + content: "\f151"; } + +.fa.fa-toggle-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-up:before { + content: "\f151"; } + +.fa.fa-caret-square-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-right:before { + content: "\f152"; } + +.fa.fa-toggle-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-right:before { + content: "\f152"; } + +.fa.fa-eur:before { + content: "\f153"; } + +.fa.fa-euro:before { + content: "\f153"; } + +.fa.fa-gbp:before { + content: "\f154"; } + +.fa.fa-usd:before { + content: "\f155"; } + +.fa.fa-dollar:before { + content: "\f155"; } + +.fa.fa-inr:before { + content: "\f156"; } + +.fa.fa-rupee:before { + content: "\f156"; } + +.fa.fa-jpy:before { + content: "\f157"; } + +.fa.fa-cny:before { + content: "\f157"; } + +.fa.fa-rmb:before { + content: "\f157"; } + +.fa.fa-yen:before { + content: "\f157"; } + +.fa.fa-rub:before { + content: "\f158"; } + +.fa.fa-ruble:before { + content: "\f158"; } + +.fa.fa-rouble:before { + content: "\f158"; } + +.fa.fa-krw:before { + content: "\f159"; } + +.fa.fa-won:before { + content: "\f159"; } + +.fa.fa-btc { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin:before { + content: "\f15a"; } + +.fa.fa-file-text:before { + content: "\f15c"; } + +.fa.fa-sort-alpha-asc:before { + content: "\f15d"; } + +.fa.fa-sort-alpha-desc:before { + content: "\f15e"; } + +.fa.fa-sort-amount-asc:before { + content: "\f160"; } + +.fa.fa-sort-amount-desc:before { + content: "\f161"; } + +.fa.fa-sort-numeric-asc:before { + content: "\f162"; } + +.fa.fa-sort-numeric-desc:before { + content: "\f163"; } + +.fa.fa-youtube-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-xing { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-xing-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube-play { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube-play:before { + content: "\f167"; } + +.fa.fa-dropbox { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stack-overflow { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-instagram { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-flickr { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-adn { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square:before { + content: "\f171"; } + +.fa.fa-tumblr { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-tumblr-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-long-arrow-down:before { + content: "\f309"; } + +.fa.fa-long-arrow-up:before { + content: "\f30c"; } + +.fa.fa-long-arrow-left:before { + content: "\f30a"; } + +.fa.fa-long-arrow-right:before { + content: "\f30b"; } + +.fa.fa-apple { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-windows { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-android { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linux { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-dribbble { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-skype { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-foursquare { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-trello { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gratipay { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gittip { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gittip:before { + content: "\f184"; } + +.fa.fa-sun-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sun-o:before { + content: "\f185"; } + +.fa.fa-moon-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-moon-o:before { + content: "\f186"; } + +.fa.fa-vk { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-weibo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-renren { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pagelines { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stack-exchange { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right:before { + content: "\f35a"; } + +.fa.fa-arrow-circle-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-left:before { + content: "\f359"; } + +.fa.fa-caret-square-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-left:before { + content: "\f191"; } + +.fa.fa-toggle-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-left:before { + content: "\f191"; } + +.fa.fa-dot-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-dot-circle-o:before { + content: "\f192"; } + +.fa.fa-vimeo-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-try:before { + content: "\f195"; } + +.fa.fa-turkish-lira:before { + content: "\f195"; } + +.fa.fa-plus-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-plus-square-o:before { + content: "\f0fe"; } + +.fa.fa-slack { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wordpress { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-openid { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-institution:before { + content: "\f19c"; } + +.fa.fa-bank:before { + content: "\f19c"; } + +.fa.fa-mortar-board:before { + content: "\f19d"; } + +.fa.fa-yahoo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stumbleupon-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stumbleupon { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-delicious { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-digg { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-pp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-drupal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-joomla { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-spoon:before { + content: "\f2e5"; } + +.fa.fa-behance { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-behance-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-steam { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-steam-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-automobile:before { + content: "\f1b9"; } + +.fa.fa-cab:before { + content: "\f1ba"; } + +.fa.fa-envelope-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-envelope-o:before { + content: "\f0e0"; } + +.fa.fa-deviantart { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-soundcloud { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-file-pdf-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-pdf-o:before { + content: "\f1c1"; } + +.fa.fa-file-word-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-word-o:before { + content: "\f1c2"; } + +.fa.fa-file-excel-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-excel-o:before { + content: "\f1c3"; } + +.fa.fa-file-powerpoint-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-powerpoint-o:before { + content: "\f1c4"; } + +.fa.fa-file-image-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-image-o:before { + content: "\f1c5"; } + +.fa.fa-file-photo-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-photo-o:before { + content: "\f1c5"; } + +.fa.fa-file-picture-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-picture-o:before { + content: "\f1c5"; } + +.fa.fa-file-archive-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-archive-o:before { + content: "\f1c6"; } + +.fa.fa-file-zip-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-zip-o:before { + content: "\f1c6"; } + +.fa.fa-file-audio-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-audio-o:before { + content: "\f1c7"; } + +.fa.fa-file-sound-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-sound-o:before { + content: "\f1c7"; } + +.fa.fa-file-video-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-video-o:before { + content: "\f1c8"; } + +.fa.fa-file-movie-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-movie-o:before { + content: "\f1c8"; } + +.fa.fa-file-code-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-code-o:before { + content: "\f1c9"; } + +.fa.fa-vine { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-codepen { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-jsfiddle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-life-ring { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-bouy { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-bouy:before { + content: "\f1cd"; } + +.fa.fa-life-buoy { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-buoy:before { + content: "\f1cd"; } + +.fa.fa-life-saver { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-saver:before { + content: "\f1cd"; } + +.fa.fa-support { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-support:before { + content: "\f1cd"; } + +.fa.fa-circle-o-notch:before { + content: "\f1ce"; } + +.fa.fa-rebel { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ra { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ra:before { + content: "\f1d0"; } + +.fa.fa-resistance { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-resistance:before { + content: "\f1d0"; } + +.fa.fa-empire { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ge { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ge:before { + content: "\f1d1"; } + +.fa.fa-git-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-git { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-hacker-news { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square:before { + content: "\f1d4"; } + +.fa.fa-yc-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc-square:before { + content: "\f1d4"; } + +.fa.fa-tencent-weibo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-qq { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-weixin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wechat { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wechat:before { + content: "\f1d7"; } + +.fa.fa-send:before { + content: "\f1d8"; } + +.fa.fa-paper-plane-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paper-plane-o:before { + content: "\f1d8"; } + +.fa.fa-send-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-send-o:before { + content: "\f1d8"; } + +.fa.fa-circle-thin { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-circle-thin:before { + content: "\f111"; } + +.fa.fa-header:before { + content: "\f1dc"; } + +.fa.fa-sliders:before { + content: "\f1de"; } + +.fa.fa-futbol-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-futbol-o:before { + content: "\f1e3"; } + +.fa.fa-soccer-ball-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-soccer-ball-o:before { + content: "\f1e3"; } + +.fa.fa-slideshare { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-twitch { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yelp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-newspaper-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-newspaper-o:before { + content: "\f1ea"; } + +.fa.fa-paypal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-wallet { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-visa { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-mastercard { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-discover { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-amex { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-paypal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-stripe { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bell-slash-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bell-slash-o:before { + content: "\f1f6"; } + +.fa.fa-trash:before { + content: "\f2ed"; } + +.fa.fa-copyright { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-eyedropper:before { + content: "\f1fb"; } + +.fa.fa-area-chart:before { + content: "\f1fe"; } + +.fa.fa-pie-chart:before { + content: "\f200"; } + +.fa.fa-line-chart:before { + content: "\f201"; } + +.fa.fa-lastfm { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-lastfm-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ioxhost { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-angellist { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-cc:before { + content: "\f20a"; } + +.fa.fa-ils:before { + content: "\f20b"; } + +.fa.fa-shekel:before { + content: "\f20b"; } + +.fa.fa-sheqel:before { + content: "\f20b"; } + +.fa.fa-meanpath { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-meanpath:before { + content: "\f2b4"; } + +.fa.fa-buysellads { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-connectdevelop { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-dashcube { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-forumbee { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-leanpub { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-sellsy { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-shirtsinbulk { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-simplybuilt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-skyatlas { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-diamond { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-diamond:before { + content: "\f3a5"; } + +.fa.fa-intersex:before { + content: "\f224"; } + +.fa.fa-facebook-official { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-official:before { + content: "\f09a"; } + +.fa.fa-pinterest-p { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-whatsapp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-hotel:before { + content: "\f236"; } + +.fa.fa-viacoin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-medium { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc:before { + content: "\f23b"; } + +.fa.fa-optin-monster { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-opencart { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-expeditedssl { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-battery-4:before { + content: "\f240"; } + +.fa.fa-battery:before { + content: "\f240"; } + +.fa.fa-battery-3:before { + content: "\f241"; } + +.fa.fa-battery-2:before { + content: "\f242"; } + +.fa.fa-battery-1:before { + content: "\f243"; } + +.fa.fa-battery-0:before { + content: "\f244"; } + +.fa.fa-object-group { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-object-ungroup { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o:before { + content: "\f249"; } + +.fa.fa-cc-jcb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-diners-club { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-clone { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hourglass-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hourglass-o:before { + content: "\f254"; } + +.fa.fa-hourglass-1:before { + content: "\f251"; } + +.fa.fa-hourglass-2:before { + content: "\f252"; } + +.fa.fa-hourglass-3:before { + content: "\f253"; } + +.fa.fa-hand-rock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-rock-o:before { + content: "\f255"; } + +.fa.fa-hand-grab-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-grab-o:before { + content: "\f255"; } + +.fa.fa-hand-paper-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-paper-o:before { + content: "\f256"; } + +.fa.fa-hand-stop-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-stop-o:before { + content: "\f256"; } + +.fa.fa-hand-scissors-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-scissors-o:before { + content: "\f257"; } + +.fa.fa-hand-lizard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-lizard-o:before { + content: "\f258"; } + +.fa.fa-hand-spock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-spock-o:before { + content: "\f259"; } + +.fa.fa-hand-pointer-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-pointer-o:before { + content: "\f25a"; } + +.fa.fa-hand-peace-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-peace-o:before { + content: "\f25b"; } + +.fa.fa-registered { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-creative-commons { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gg { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gg-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-tripadvisor { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-get-pocket { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wikipedia-w { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-safari { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-chrome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-firefox { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-opera { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-internet-explorer { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-television:before { + content: "\f26c"; } + +.fa.fa-contao { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-500px { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-amazon { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-calendar-plus-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-plus-o:before { + content: "\f271"; } + +.fa.fa-calendar-minus-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-minus-o:before { + content: "\f272"; } + +.fa.fa-calendar-times-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-times-o:before { + content: "\f273"; } + +.fa.fa-calendar-check-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-check-o:before { + content: "\f274"; } + +.fa.fa-map-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-map-o:before { + content: "\f279"; } + +.fa.fa-commenting { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-commenting:before { + content: "\f4ad"; } + +.fa.fa-commenting-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-commenting-o:before { + content: "\f4ad"; } + +.fa.fa-houzz { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-vimeo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-vimeo:before { + content: "\f27d"; } + +.fa.fa-black-tie { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fonticons { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit-alien { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-edge { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-credit-card-alt:before { + content: "\f09d"; } + +.fa.fa-codiepie { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-modx { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fort-awesome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-usb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-product-hunt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-mixcloud { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-scribd { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pause-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-pause-circle-o:before { + content: "\f28b"; } + +.fa.fa-stop-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-stop-circle-o:before { + content: "\f28d"; } + +.fa.fa-bluetooth { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bluetooth-b { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gitlab { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpbeginner { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpforms { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-envira { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt:before { + content: "\f368"; } + +.fa.fa-question-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-question-circle-o:before { + content: "\f059"; } + +.fa.fa-volume-control-phone:before { + content: "\f2a0"; } + +.fa.fa-asl-interpreting:before { + content: "\f2a3"; } + +.fa.fa-deafness:before { + content: "\f2a4"; } + +.fa.fa-hard-of-hearing:before { + content: "\f2a4"; } + +.fa.fa-glide { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-glide-g { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-signing:before { + content: "\f2a7"; } + +.fa.fa-viadeo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-viadeo-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-ghost { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-first-order { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yoast { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-themeisle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official:before { + content: "\f2b3"; } + +.fa.fa-google-plus-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-circle:before { + content: "\f2b3"; } + +.fa.fa-font-awesome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fa { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fa:before { + content: "\f2b4"; } + +.fa.fa-handshake-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-handshake-o:before { + content: "\f2b5"; } + +.fa.fa-envelope-open-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-envelope-open-o:before { + content: "\f2b6"; } + +.fa.fa-linode { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-address-book-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-address-book-o:before { + content: "\f2b9"; } + +.fa.fa-vcard:before { + content: "\f2bb"; } + +.fa.fa-address-card-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-address-card-o:before { + content: "\f2bb"; } + +.fa.fa-vcard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-vcard-o:before { + content: "\f2bb"; } + +.fa.fa-user-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-user-circle-o:before { + content: "\f2bd"; } + +.fa.fa-user-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-user-o:before { + content: "\f007"; } + +.fa.fa-id-badge { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-drivers-license:before { + content: "\f2c2"; } + +.fa.fa-id-card-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-id-card-o:before { + content: "\f2c2"; } + +.fa.fa-drivers-license-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-drivers-license-o:before { + content: "\f2c2"; } + +.fa.fa-quora { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-free-code-camp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-telegram { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-thermometer-4:before { + content: "\f2c7"; } + +.fa.fa-thermometer:before { + content: "\f2c7"; } + +.fa.fa-thermometer-3:before { + content: "\f2c8"; } + +.fa.fa-thermometer-2:before { + content: "\f2c9"; } + +.fa.fa-thermometer-1:before { + content: "\f2ca"; } + +.fa.fa-thermometer-0:before { + content: "\f2cb"; } + +.fa.fa-bathtub:before { + content: "\f2cd"; } + +.fa.fa-s15:before { + content: "\f2cd"; } + +.fa.fa-window-maximize { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-window-restore { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle:before { + content: "\f410"; } + +.fa.fa-window-close-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-window-close-o:before { + content: "\f410"; } + +.fa.fa-times-rectangle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle-o:before { + content: "\f410"; } + +.fa.fa-bandcamp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-grav { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-etsy { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-imdb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ravelry { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-eercast { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-eercast:before { + content: "\f2da"; } + +.fa.fa-snowflake-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-snowflake-o:before { + content: "\f2dc"; } + +.fa.fa-superpowers { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpexplorer { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-spotify { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.eot b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.eot new file mode 100644 index 00000000..f8e48185 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.eot differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.svg b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.svg new file mode 100644 index 00000000..68eb65a1 --- /dev/null +++ b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.svg @@ -0,0 +1,1127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.ttf b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.ttf new file mode 100644 index 00000000..2b00dae7 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.ttf differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff new file mode 100644 index 00000000..9e4b7e1c Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff2 b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff2 new file mode 100644 index 00000000..b9e58c5e Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-brands-400.woff2 differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.eot b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.eot new file mode 100644 index 00000000..5217c95f Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.eot differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.svg b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.svg new file mode 100644 index 00000000..5f495431 --- /dev/null +++ b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.svg @@ -0,0 +1,467 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.ttf b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.ttf new file mode 100644 index 00000000..cefbd50f Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.ttf differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff new file mode 100644 index 00000000..954b0593 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff2 b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff2 new file mode 100644 index 00000000..bd35950e Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-regular-400.woff2 differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.eot b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.eot new file mode 100644 index 00000000..cc691d63 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.eot differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.svg b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.svg new file mode 100644 index 00000000..1534b64b --- /dev/null +++ b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.svg @@ -0,0 +1,2231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.ttf b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.ttf new file mode 100644 index 00000000..618136ab Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.ttf differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff new file mode 100644 index 00000000..af476578 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff differ diff --git a/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff2 b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff2 new file mode 100644 index 00000000..9ef566a9 Binary files /dev/null and b/docs/site_libs/font-awesome-5.1.0/webfonts/fa-solid-900.woff2 differ diff --git a/docs/site_libs/fuse-6.4.1/fuse.min.js b/docs/site_libs/fuse-6.4.1/fuse.min.js new file mode 100644 index 00000000..02ab1f24 --- /dev/null +++ b/docs/site_libs/fuse-6.4.1/fuse.min.js @@ -0,0 +1,9 @@ +/** + * Fuse.js v6.4.1 - Lightweight fuzzy-search (http://fusejs.io) + * + * Copyright (c) 2020 Kiro Risk (http://kiro.me) + * All Rights Reserved. Apache Software License 2.0 + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +var e,t;e=this,t=function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function n(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:3,t=new Map;return{get:function(n){var r=n.match(I).length;if(t.has(r))return t.get(r);var i=parseFloat((1/Math.sqrt(r)).toFixed(e));return t.set(r,i),i},clear:function(){t.clear()}}}var E=function(){function e(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.getFn,i=void 0===r?A.getFn:r;t(this,e),this.norm=C(3),this.getFn=i,this.isCreated=!1,this.setIndexRecords()}return r(e,[{key:"setSources",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.docs=e}},{key:"setIndexRecords",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.records=e}},{key:"setKeys",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.keys=t,this._keysMap={},t.forEach((function(t,n){e._keysMap[t.id]=n}))}},{key:"create",value:function(){var e=this;!this.isCreated&&this.docs.length&&(this.isCreated=!0,g(this.docs[0])?this.docs.forEach((function(t,n){e._addString(t,n)})):this.docs.forEach((function(t,n){e._addObject(t,n)})),this.norm.clear())}},{key:"add",value:function(e){var t=this.size();g(e)?this._addString(e,t):this._addObject(e,t)}},{key:"removeAt",value:function(e){this.records.splice(e,1);for(var t=e,n=this.size();t2&&void 0!==arguments[2]?arguments[2]:{},r=n.getFn,i=void 0===r?A.getFn:r,o=new E({getFn:i});return o.setKeys(e.map(L)),o.setSources(t),o.create(),o}function R(e,t){var n=e.matches;t.matches=[],k(n)&&n.forEach((function(e){if(k(e.indices)&&e.indices.length){var n={indices:e.indices,value:e.value};e.key&&(n.key=e.key.src),e.idx>-1&&(n.refIndex=e.idx),t.matches.push(n)}}))}function F(e,t){t.score=e.score}function P(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.errors,r=void 0===n?0:n,i=t.currentLocation,o=void 0===i?0:i,c=t.expectedLocation,a=void 0===c?0:c,s=t.distance,u=void 0===s?A.distance:s,h=t.ignoreLocation,f=void 0===h?A.ignoreLocation:h,l=r/e.length;if(f)return l;var d=Math.abs(a-o);return u?l+d/u:d?1:l}function N(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:A.minMatchCharLength,n=[],r=-1,i=-1,o=0,c=e.length;o=t&&n.push([r,i]),r=-1)}return e[o-1]&&o-r>=t&&n.push([r,o-1]),n}function D(e){for(var t={},n=0,r=e.length;n1&&void 0!==arguments[1]?arguments[1]:{},o=i.location,c=void 0===o?A.location:o,a=i.threshold,s=void 0===a?A.threshold:a,u=i.distance,h=void 0===u?A.distance:u,f=i.includeMatches,l=void 0===f?A.includeMatches:f,d=i.findAllMatches,v=void 0===d?A.findAllMatches:d,g=i.minMatchCharLength,y=void 0===g?A.minMatchCharLength:g,p=i.isCaseSensitive,m=void 0===p?A.isCaseSensitive:p,k=i.ignoreLocation,M=void 0===k?A.ignoreLocation:k;if(t(this,e),this.options={location:c,threshold:s,distance:h,includeMatches:l,findAllMatches:v,minMatchCharLength:y,isCaseSensitive:m,ignoreLocation:M},this.pattern=m?n:n.toLowerCase(),this.chunks=[],this.pattern.length){var x=function(e,t){r.chunks.push({pattern:e,alphabet:D(e),startIndex:t})},b=this.pattern.length;if(b>32){for(var S=0,_=b%32,w=b-_;S3&&void 0!==arguments[3]?arguments[3]:{},i=r.location,o=void 0===i?A.location:i,c=r.distance,a=void 0===c?A.distance:c,s=r.threshold,u=void 0===s?A.threshold:s,h=r.findAllMatches,f=void 0===h?A.findAllMatches:h,l=r.minMatchCharLength,d=void 0===l?A.minMatchCharLength:l,v=r.includeMatches,g=void 0===v?A.includeMatches:v,y=r.ignoreLocation,p=void 0===y?A.ignoreLocation:y;if(t.length>32)throw new Error(S(32));for(var m,k=t.length,M=e.length,x=Math.max(0,Math.min(o,M)),b=u,_=x,w=d>1||g,L=w?Array(M):[];(m=e.indexOf(t,_))>-1;){var O=P(t,{currentLocation:m,expectedLocation:x,distance:a,ignoreLocation:p});if(b=Math.min(O,b),_=m+k,w)for(var j=0;j=K;J-=1){var T=J-1,U=n[e.charAt(T)];if(w&&(L[T]=+!!U),W[J]=(W[J+1]<<1|1)&U,R&&(W[J]|=(I[J+1]|I[J])<<1|1|I[J+1]),W[J]&$&&(C=P(t,{errors:R,currentLocation:T,expectedLocation:x,distance:a,ignoreLocation:p}))<=b){if(b=C,(_=T)<=x)break;K=Math.max(1,2*x-_)}}var V=P(t,{errors:R+1,currentLocation:x,expectedLocation:x,distance:a,ignoreLocation:p});if(V>b)break;I=W}var B={isMatch:_>=0,score:Math.max(.001,C)};if(w){var G=N(L,d);G.length?g&&(B.indices=G):B.isMatch=!1}return B}(e,n,i,{location:c+o,distance:a,threshold:s,findAllMatches:u,minMatchCharLength:h,includeMatches:r,ignoreLocation:f}),p=y.isMatch,m=y.score,k=y.indices;p&&(g=!0),v+=m,p&&k&&(d=[].concat(l(d),l(k)))}));var y={isMatch:g,score:g?v/this.chunks.length:1};return g&&r&&(y.indices=d),y}}]),e}(),K=function(){function e(n){t(this,e),this.pattern=n}return r(e,[{key:"search",value:function(){}}],[{key:"isMultiMatch",value:function(e){return q(e,this.multiRegex)}},{key:"isSingleMatch",value:function(e){return q(e,this.singleRegex)}}]),e}();function q(e,t){var n=e.match(t);return n?n[1]:null}var W=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"exact"}},{key:"multiRegex",get:function(){return/^="(.*)"$/}},{key:"singleRegex",get:function(){return/^=(.*)$/}}]),i}(K),J=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"$/}},{key:"singleRegex",get:function(){return/^!(.*)$/}}]),i}(K),T=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"prefix-exact"}},{key:"multiRegex",get:function(){return/^\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^\^(.*)$/}}]),i}(K),U=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-prefix-exact"}},{key:"multiRegex",get:function(){return/^!\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^!\^(.*)$/}}]),i}(K),V=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}],[{key:"type",get:function(){return"suffix-exact"}},{key:"multiRegex",get:function(){return/^"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^(.*)\$$/}}]),i}(K),B=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){var t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-suffix-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^!(.*)\$$/}}]),i}(K),G=function(e){a(i,e);var n=f(i);function i(e){var r,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=o.location,a=void 0===c?A.location:c,s=o.threshold,u=void 0===s?A.threshold:s,h=o.distance,f=void 0===h?A.distance:h,l=o.includeMatches,d=void 0===l?A.includeMatches:l,v=o.findAllMatches,g=void 0===v?A.findAllMatches:v,y=o.minMatchCharLength,p=void 0===y?A.minMatchCharLength:y,m=o.isCaseSensitive,k=void 0===m?A.isCaseSensitive:m;return t(this,i),(r=n.call(this,e))._bitapSearch=new z(e,{location:a,threshold:u,distance:f,includeMatches:d,findAllMatches:g,minMatchCharLength:p,isCaseSensitive:k}),r}return r(i,[{key:"search",value:function(e){return this._bitapSearch.searchIn(e)}}],[{key:"type",get:function(){return"fuzzy"}},{key:"multiRegex",get:function(){return/^"(.*)"$/}},{key:"singleRegex",get:function(){return/^(.*)$/}}]),i}(K),H=function(e){a(i,e);var n=f(i);function i(e){return t(this,i),n.call(this,e)}return r(i,[{key:"search",value:function(e){for(var t,n=0,r=[],i=this.pattern.length;(t=e.indexOf(this.pattern,n))>-1;)n=t+i,r.push([t,n-1]);var o=!!r.length;return{isMatch:o,score:o?1:0,indices:r}}}],[{key:"type",get:function(){return"include"}},{key:"multiRegex",get:function(){return/^'"(.*)"$/}},{key:"singleRegex",get:function(){return/^'(.*)$/}}]),i}(K),Q=[W,H,T,U,B,V,J,G],X=Q.length,Y=/ +(?=([^\"]*\"[^\"]*\")*[^\"]*$)/;function Z(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.split("|").map((function(e){for(var n=e.trim().split(Y).filter((function(e){return e&&!!e.trim()})),r=[],i=0,o=n.length;i1&&void 0!==arguments[1]?arguments[1]:{},i=r.isCaseSensitive,o=void 0===i?A.isCaseSensitive:i,c=r.includeMatches,a=void 0===c?A.includeMatches:c,s=r.minMatchCharLength,u=void 0===s?A.minMatchCharLength:s,h=r.findAllMatches,f=void 0===h?A.findAllMatches:h,l=r.location,d=void 0===l?A.location:l,v=r.threshold,g=void 0===v?A.threshold:v,y=r.distance,p=void 0===y?A.distance:y;t(this,e),this.query=null,this.options={isCaseSensitive:o,includeMatches:a,minMatchCharLength:u,findAllMatches:f,location:d,threshold:g,distance:p},this.pattern=o?n:n.toLowerCase(),this.query=Z(this.pattern,this.options)}return r(e,[{key:"searchIn",value:function(e){var t=this.query;if(!t)return{isMatch:!1,score:1};var n=this.options,r=n.includeMatches;e=n.isCaseSensitive?e:e.toLowerCase();for(var i=0,o=[],c=0,a=0,s=t.length;a1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2?arguments[2]:void 0;t(this,e),this.options=c({},A,{},r),this.options.useExtendedSearch,this._keyStore=new w(this.options.keys),this.setCollection(n,i)}return r(e,[{key:"setCollection",value:function(e,t){if(this._docs=e,t&&!(t instanceof E))throw new Error("Incorrect 'index' type");this._myIndex=t||$(this.options.keys,this._docs,{getFn:this.options.getFn})}},{key:"add",value:function(e){k(e)&&(this._docs.push(e),this._myIndex.add(e))}},{key:"remove",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!1},t=[],n=0,r=this._docs.length;n1&&void 0!==arguments[1]?arguments[1]:{},n=t.limit,r=void 0===n?-1:n,i=this.options,o=i.includeMatches,c=i.includeScore,a=i.shouldSort,s=i.sortFn,u=i.ignoreFieldNorm,h=g(e)?g(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return de(h,{ignoreFieldNorm:u}),a&&h.sort(s),y(r)&&r>-1&&(h=h.slice(0,r)),ve(h,this._docs,{includeMatches:o,includeScore:c})}},{key:"_searchStringList",value:function(e){var t=re(e,this.options),n=this._myIndex.records,r=[];return n.forEach((function(e){var n=e.v,i=e.i,o=e.n;if(k(n)){var c=t.searchIn(n),a=c.isMatch,s=c.score,u=c.indices;a&&r.push({item:n,idx:i,matches:[{score:s,value:n,norm:o,indices:u}]})}})),r}},{key:"_searchLogical",value:function(e){var t=this,n=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.auto,i=void 0===r||r,o=function e(n){var r=Object.keys(n),o=ue(n);if(!o&&r.length>1&&!se(n))return e(fe(n));if(he(n)){var c=o?n[ce]:r[0],a=o?n[ae]:n[c];if(!g(a))throw new Error(b(c));var s={keyId:j(c),pattern:a};return i&&(s.searcher=re(a,t)),s}var u={children:[],operator:r[0]};return r.forEach((function(t){var r=n[t];v(r)&&r.forEach((function(t){u.children.push(e(t))}))})),u};return se(e)||(e=fe(e)),o(e)}(e,this.options),r=this._myIndex.records,i={},o=[];return r.forEach((function(e){var r=e.$,c=e.i;if(k(r)){var a=function e(n,r,i){if(!n.children){var o=n.keyId,c=n.searcher,a=t._findMatches({key:t._keyStore.get(o),value:t._myIndex.getValueForItemAtKeyId(r,o),searcher:c});return a&&a.length?[{idx:i,item:r,matches:a}]:[]}switch(n.operator){case ie:for(var s=[],u=0,h=n.children.length;u2&&void 0!==arguments[2]?arguments[2]:{},r=n.includeMatches,i=void 0===r?A.includeMatches:r,o=n.includeScore,c=void 0===o?A.includeScore:o,a=[];return i&&a.push(R),c&&a.push(F),e.map((function(e){var n=e.idx,r={item:t[n],refIndex:n};return a.length&&a.forEach((function(t){t(e,r)})),r}))}return le.version="6.4.1",le.createIndex=$,le.parseIndex=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.getFn,r=void 0===n?A.getFn:n,i=e.keys,o=e.records,c=new E({getFn:r});return c.setKeys(i),c.setIndexRecords(o),c},le.config=A,function(){ne.push.apply(ne,arguments)}(te),le},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Fuse=t(); \ No newline at end of file diff --git a/docs/site_libs/header-attrs-2.11/header-attrs.js b/docs/site_libs/header-attrs-2.11/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/site_libs/header-attrs-2.11/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/site_libs/header-attrs-2.5/header-attrs.js b/docs/site_libs/header-attrs-2.5/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/site_libs/header-attrs-2.5/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/site_libs/header-attrs-2.6/header-attrs.js b/docs/site_libs/header-attrs-2.6/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/site_libs/header-attrs-2.6/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/site_libs/header-attrs-2.8/header-attrs.js b/docs/site_libs/header-attrs-2.8/header-attrs.js new file mode 100644 index 00000000..dd57d92e --- /dev/null +++ b/docs/site_libs/header-attrs-2.8/header-attrs.js @@ -0,0 +1,12 @@ +// Pandoc 2.9 adds attributes on both header and div. We remove the former (to +// be compatible with the behavior of Pandoc < 2.8). +document.addEventListener('DOMContentLoaded', function(e) { + var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); + var i, h, a; + for (i = 0; i < hs.length; i++) { + h = hs[i]; + if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 + a = h.attributes; + while (a.length > 0) h.removeAttribute(a[0].name); + } +}); diff --git a/docs/site_libs/headroom-0.9.4/headroom.min.js b/docs/site_libs/headroom-0.9.4/headroom.min.js new file mode 100644 index 00000000..39a74e34 --- /dev/null +++ b/docs/site_libs/headroom-0.9.4/headroom.min.js @@ -0,0 +1,7 @@ +/*! + * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it + * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js + * License: MIT + */ + +!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.Headroom=b()}(this,function(){"use strict";function a(a){this.callback=a,this.ticking=!1}function b(a){return a&&"undefined"!=typeof window&&(a===window||a.nodeType)}function c(a){if(arguments.length<=0)throw new Error("Missing arguments in extend function");var d,e,f=a||{};for(e=1;ethis.getScrollerHeight();return b||c},toleranceExceeded:function(a,b){return Math.abs(a-this.lastKnownScrollY)>=this.tolerance[b]},shouldUnpin:function(a,b){var c=a>this.lastKnownScrollY,d=a>=this.offset;return c&&d&&b},shouldPin:function(a,b){var c=athis.lastKnownScrollY?"down":"up",c=this.toleranceExceeded(a,b);this.isOutOfBounds(a)||(a<=this.offset?this.top():this.notTop(),a+this.getViewportHeight()>=this.getScrollerHeight()?this.bottom():this.notBottom(),this.shouldUnpin(a,c)?this.unpin():this.shouldPin(a,c)&&this.pin(),this.lastKnownScrollY=a)}},e.options={tolerance:{up:0,down:0},offset:0,scroller:window,classes:{pinned:"headroom--pinned",unpinned:"headroom--unpinned",top:"headroom--top",notTop:"headroom--not-top",bottom:"headroom--bottom",notBottom:"headroom--not-bottom",initial:"headroom"}},e.cutsTheMustard="undefined"!=typeof f&&f.rAF&&f.bind&&f.classList,e}); \ No newline at end of file diff --git a/docs/site_libs/htmlwidgets-1.5.2/htmlwidgets.js b/docs/site_libs/htmlwidgets-1.5.2/htmlwidgets.js new file mode 100644 index 00000000..6f3d672d --- /dev/null +++ b/docs/site_libs/htmlwidgets-1.5.2/htmlwidgets.js @@ -0,0 +1,903 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval(code); + } catch(error) { + if (!error instanceof SyntaxError) { + throw error; + } + try { + result = eval("(" + code + ")"); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + if (cel) { + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + } + + return { + getWidth: function() { return cel.offsetWidth; }, + getHeight: function() { return cel.offsetHeight; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return el.offsetWidth; }, + getHeight: function() { return el.offsetHeight; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
      ").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var result = bindingDef.initialize(el, el.offsetWidth, + el.offsetHeight); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + initResult = binding.initialize(el, + sizeObj ? sizeObj.getWidth() : el.offsetWidth, + sizeObj ? sizeObj.getHeight() : el.offsetHeight + ); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + var resizeHandler = function(e) { + var size = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); + diff --git a/docs/site_libs/htmlwidgets-1.5.3/htmlwidgets.js b/docs/site_libs/htmlwidgets-1.5.3/htmlwidgets.js new file mode 100644 index 00000000..3d227624 --- /dev/null +++ b/docs/site_libs/htmlwidgets-1.5.3/htmlwidgets.js @@ -0,0 +1,903 @@ +(function() { + // If window.HTMLWidgets is already defined, then use it; otherwise create a + // new object. This allows preceding code to set options that affect the + // initialization process (though none currently exist). + window.HTMLWidgets = window.HTMLWidgets || {}; + + // See if we're running in a viewer pane. If not, we're in a web browser. + var viewerMode = window.HTMLWidgets.viewerMode = + /\bviewer_pane=1\b/.test(window.location); + + // See if we're running in Shiny mode. If not, it's a static document. + // Note that static widgets can appear in both Shiny and static modes, but + // obviously, Shiny widgets can only appear in Shiny apps/documents. + var shinyMode = window.HTMLWidgets.shinyMode = + typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings; + + // We can't count on jQuery being available, so we implement our own + // version if necessary. + function querySelectorAll(scope, selector) { + if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) { + return scope.find(selector); + } + if (scope.querySelectorAll) { + return scope.querySelectorAll(selector); + } + } + + function asArray(value) { + if (value === null) + return []; + if ($.isArray(value)) + return value; + return [value]; + } + + // Implement jQuery's extend + function extend(target /*, ... */) { + if (arguments.length == 1) { + return target; + } + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + return target; + } + + // IE8 doesn't support Array.forEach. + function forEach(values, callback, thisArg) { + if (values.forEach) { + values.forEach(callback, thisArg); + } else { + for (var i = 0; i < values.length; i++) { + callback.call(thisArg, values[i], i, values); + } + } + } + + // Replaces the specified method with the return value of funcSource. + // + // Note that funcSource should not BE the new method, it should be a function + // that RETURNS the new method. funcSource receives a single argument that is + // the overridden method, it can be called from the new method. The overridden + // method can be called like a regular function, it has the target permanently + // bound to it so "this" will work correctly. + function overrideMethod(target, methodName, funcSource) { + var superFunc = target[methodName] || function() {}; + var superFuncBound = function() { + return superFunc.apply(target, arguments); + }; + target[methodName] = funcSource(superFuncBound); + } + + // Add a method to delegator that, when invoked, calls + // delegatee.methodName. If there is no such method on + // the delegatee, but there was one on delegator before + // delegateMethod was called, then the original version + // is invoked instead. + // For example: + // + // var a = { + // method1: function() { console.log('a1'); } + // method2: function() { console.log('a2'); } + // }; + // var b = { + // method1: function() { console.log('b1'); } + // }; + // delegateMethod(a, b, "method1"); + // delegateMethod(a, b, "method2"); + // a.method1(); + // a.method2(); + // + // The output would be "b1", "a2". + function delegateMethod(delegator, delegatee, methodName) { + var inherited = delegator[methodName]; + delegator[methodName] = function() { + var target = delegatee; + var method = delegatee[methodName]; + + // The method doesn't exist on the delegatee. Instead, + // call the method on the delegator, if it exists. + if (!method) { + target = delegator; + method = inherited; + } + + if (method) { + return method.apply(target, arguments); + } + }; + } + + // Implement a vague facsimilie of jQuery's data method + function elementData(el, name, value) { + if (arguments.length == 2) { + return el["htmlwidget_data_" + name]; + } else if (arguments.length == 3) { + el["htmlwidget_data_" + name] = value; + return el; + } else { + throw new Error("Wrong number of arguments for elementData: " + + arguments.length); + } + } + + // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex + function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + + function hasClass(el, className) { + var re = new RegExp("\\b" + escapeRegExp(className) + "\\b"); + return re.test(el.className); + } + + // elements - array (or array-like object) of HTML elements + // className - class name to test for + // include - if true, only return elements with given className; + // if false, only return elements *without* given className + function filterByClass(elements, className, include) { + var results = []; + for (var i = 0; i < elements.length; i++) { + if (hasClass(elements[i], className) == include) + results.push(elements[i]); + } + return results; + } + + function on(obj, eventName, func) { + if (obj.addEventListener) { + obj.addEventListener(eventName, func, false); + } else if (obj.attachEvent) { + obj.attachEvent(eventName, func); + } + } + + function off(obj, eventName, func) { + if (obj.removeEventListener) + obj.removeEventListener(eventName, func, false); + else if (obj.detachEvent) { + obj.detachEvent(eventName, func); + } + } + + // Translate array of values to top/right/bottom/left, as usual with + // the "padding" CSS property + // https://developer.mozilla.org/en-US/docs/Web/CSS/padding + function unpackPadding(value) { + if (typeof(value) === "number") + value = [value]; + if (value.length === 1) { + return {top: value[0], right: value[0], bottom: value[0], left: value[0]}; + } + if (value.length === 2) { + return {top: value[0], right: value[1], bottom: value[0], left: value[1]}; + } + if (value.length === 3) { + return {top: value[0], right: value[1], bottom: value[2], left: value[1]}; + } + if (value.length === 4) { + return {top: value[0], right: value[1], bottom: value[2], left: value[3]}; + } + } + + // Convert an unpacked padding object to a CSS value + function paddingToCss(paddingObj) { + return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px"; + } + + // Makes a number suitable for CSS + function px(x) { + if (typeof(x) === "number") + return x + "px"; + else + return x; + } + + // Retrieves runtime widget sizing information for an element. + // The return value is either null, or an object with fill, padding, + // defaultWidth, defaultHeight fields. + function sizingPolicy(el) { + var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']"); + if (!sizingEl) + return null; + var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}"); + if (viewerMode) { + return sp.viewer; + } else { + return sp.browser; + } + } + + // @param tasks Array of strings (or falsy value, in which case no-op). + // Each element must be a valid JavaScript expression that yields a + // function. Or, can be an array of objects with "code" and "data" + // properties; in this case, the "code" property should be a string + // of JS that's an expr that yields a function, and "data" should be + // an object that will be added as an additional argument when that + // function is called. + // @param target The object that will be "this" for each function + // execution. + // @param args Array of arguments to be passed to the functions. (The + // same arguments will be passed to all functions.) + function evalAndRun(tasks, target, args) { + if (tasks) { + forEach(tasks, function(task) { + var theseArgs = args; + if (typeof(task) === "object") { + theseArgs = theseArgs.concat([task.data]); + task = task.code; + } + var taskFunc = tryEval(task); + if (typeof(taskFunc) !== "function") { + throw new Error("Task must be a function! Source:\n" + task); + } + taskFunc.apply(target, theseArgs); + }); + } + } + + // Attempt eval() both with and without enclosing in parentheses. + // Note that enclosing coerces a function declaration into + // an expression that eval() can parse + // (otherwise, a SyntaxError is thrown) + function tryEval(code) { + var result = null; + try { + result = eval("(" + code + ")"); + } catch(error) { + if (!error instanceof SyntaxError) { + throw error; + } + try { + result = eval(code); + } catch(e) { + if (e instanceof SyntaxError) { + throw error; + } else { + throw e; + } + } + } + return result; + } + + function initSizing(el) { + var sizing = sizingPolicy(el); + if (!sizing) + return; + + var cel = document.getElementById("htmlwidget_container"); + if (!cel) + return; + + if (typeof(sizing.padding) !== "undefined") { + document.body.style.margin = "0"; + document.body.style.padding = paddingToCss(unpackPadding(sizing.padding)); + } + + if (sizing.fill) { + document.body.style.overflow = "hidden"; + document.body.style.width = "100%"; + document.body.style.height = "100%"; + document.documentElement.style.width = "100%"; + document.documentElement.style.height = "100%"; + if (cel) { + cel.style.position = "absolute"; + var pad = unpackPadding(sizing.padding); + cel.style.top = pad.top + "px"; + cel.style.right = pad.right + "px"; + cel.style.bottom = pad.bottom + "px"; + cel.style.left = pad.left + "px"; + el.style.width = "100%"; + el.style.height = "100%"; + } + + return { + getWidth: function() { return cel.offsetWidth; }, + getHeight: function() { return cel.offsetHeight; } + }; + + } else { + el.style.width = px(sizing.width); + el.style.height = px(sizing.height); + + return { + getWidth: function() { return el.offsetWidth; }, + getHeight: function() { return el.offsetHeight; } + }; + } + } + + // Default implementations for methods + var defaults = { + find: function(scope) { + return querySelectorAll(scope, "." + this.name); + }, + renderError: function(el, err) { + var $el = $(el); + + this.clearError(el); + + // Add all these error classes, as Shiny does + var errClass = "shiny-output-error"; + if (err.type !== null) { + // use the classes of the error condition as CSS class names + errClass = errClass + " " + $.map(asArray(err.type), function(type) { + return errClass + "-" + type; + }).join(" "); + } + errClass = errClass + " htmlwidgets-error"; + + // Is el inline or block? If inline or inline-block, just display:none it + // and add an inline error. + var display = $el.css("display"); + $el.data("restore-display-mode", display); + + if (display === "inline" || display === "inline-block") { + $el.hide(); + if (err.message !== "") { + var errorSpan = $("").addClass(errClass); + errorSpan.text(err.message); + $el.after(errorSpan); + } + } else if (display === "block") { + // If block, add an error just after the el, set visibility:none on the + // el, and position the error to be on top of the el. + // Mark it with a unique ID and CSS class so we can remove it later. + $el.css("visibility", "hidden"); + if (err.message !== "") { + var errorDiv = $("
      ").addClass(errClass).css("position", "absolute") + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + // setting width can push out the page size, forcing otherwise + // unnecessary scrollbars to appear and making it impossible for + // the element to shrink; so use max-width instead + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + errorDiv.text(err.message); + $el.after(errorDiv); + + // Really dumb way to keep the size/position of the error in sync with + // the parent element as the window is resized or whatever. + var intId = setInterval(function() { + if (!errorDiv[0].parentElement) { + clearInterval(intId); + return; + } + errorDiv + .css("top", el.offsetTop) + .css("left", el.offsetLeft) + .css("maxWidth", el.offsetWidth) + .css("height", el.offsetHeight); + }, 500); + } + } + }, + clearError: function(el) { + var $el = $(el); + var display = $el.data("restore-display-mode"); + $el.data("restore-display-mode", null); + + if (display === "inline" || display === "inline-block") { + if (display) + $el.css("display", display); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } else if (display === "block"){ + $el.css("visibility", "inherit"); + $(el.nextSibling).filter(".htmlwidgets-error").remove(); + } + }, + sizing: {} + }; + + // Called by widget bindings to register a new type of widget. The definition + // object can contain the following properties: + // - name (required) - A string indicating the binding name, which will be + // used by default as the CSS classname to look for. + // - initialize (optional) - A function(el) that will be called once per + // widget element; if a value is returned, it will be passed as the third + // value to renderValue. + // - renderValue (required) - A function(el, data, initValue) that will be + // called with data. Static contexts will cause this to be called once per + // element; Shiny apps will cause this to be called multiple times per + // element, as the data changes. + window.HTMLWidgets.widget = function(definition) { + if (!definition.name) { + throw new Error("Widget must have a name"); + } + if (!definition.type) { + throw new Error("Widget must have a type"); + } + // Currently we only support output widgets + if (definition.type !== "output") { + throw new Error("Unrecognized widget type '" + definition.type + "'"); + } + // TODO: Verify that .name is a valid CSS classname + + // Support new-style instance-bound definitions. Old-style class-bound + // definitions have one widget "object" per widget per type/class of + // widget; the renderValue and resize methods on such widget objects + // take el and instance arguments, because the widget object can't + // store them. New-style instance-bound definitions have one widget + // object per widget instance; the definition that's passed in doesn't + // provide renderValue or resize methods at all, just the single method + // factory(el, width, height) + // which returns an object that has renderValue(x) and resize(w, h). + // This enables a far more natural programming style for the widget + // author, who can store per-instance state using either OO-style + // instance fields or functional-style closure variables (I guess this + // is in contrast to what can only be called C-style pseudo-OO which is + // what we required before). + if (definition.factory) { + definition = createLegacyDefinitionAdapter(definition); + } + + if (!definition.renderValue) { + throw new Error("Widget must have a renderValue function"); + } + + // For static rendering (non-Shiny), use a simple widget registration + // scheme. We also use this scheme for Shiny apps/documents that also + // contain static widgets. + window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || []; + // Merge defaults into the definition; don't mutate the original definition. + var staticBinding = extend({}, defaults, definition); + overrideMethod(staticBinding, "find", function(superfunc) { + return function(scope) { + var results = superfunc(scope); + // Filter out Shiny outputs, we only want the static kind + return filterByClass(results, "html-widget-output", false); + }; + }); + window.HTMLWidgets.widgets.push(staticBinding); + + if (shinyMode) { + // Shiny is running. Register the definition with an output binding. + // The definition itself will not be the output binding, instead + // we will make an output binding object that delegates to the + // definition. This is because we foolishly used the same method + // name (renderValue) for htmlwidgets definition and Shiny bindings + // but they actually have quite different semantics (the Shiny + // bindings receive data that includes lots of metadata that it + // strips off before calling htmlwidgets renderValue). We can't + // just ignore the difference because in some widgets it's helpful + // to call this.renderValue() from inside of resize(), and if + // we're not delegating, then that call will go to the Shiny + // version instead of the htmlwidgets version. + + // Merge defaults with definition, without mutating either. + var bindingDef = extend({}, defaults, definition); + + // This object will be our actual Shiny binding. + var shinyBinding = new Shiny.OutputBinding(); + + // With a few exceptions, we'll want to simply use the bindingDef's + // version of methods if they are available, otherwise fall back to + // Shiny's defaults. NOTE: If Shiny's output bindings gain additional + // methods in the future, and we want them to be overrideable by + // HTMLWidget binding definitions, then we'll need to add them to this + // list. + delegateMethod(shinyBinding, bindingDef, "getId"); + delegateMethod(shinyBinding, bindingDef, "onValueChange"); + delegateMethod(shinyBinding, bindingDef, "onValueError"); + delegateMethod(shinyBinding, bindingDef, "renderError"); + delegateMethod(shinyBinding, bindingDef, "clearError"); + delegateMethod(shinyBinding, bindingDef, "showProgress"); + + // The find, renderValue, and resize are handled differently, because we + // want to actually decorate the behavior of the bindingDef methods. + + shinyBinding.find = function(scope) { + var results = bindingDef.find(scope); + + // Only return elements that are Shiny outputs, not static ones + var dynamicResults = results.filter(".html-widget-output"); + + // It's possible that whatever caused Shiny to think there might be + // new dynamic outputs, also caused there to be new static outputs. + // Since there might be lots of different htmlwidgets bindings, we + // schedule execution for later--no need to staticRender multiple + // times. + if (results.length !== dynamicResults.length) + scheduleStaticRender(); + + return dynamicResults; + }; + + // Wrap renderValue to handle initialization, which unfortunately isn't + // supported natively by Shiny at the time of this writing. + + shinyBinding.renderValue = function(el, data) { + Shiny.renderDependencies(data.deps); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var i = 0; data.evals && i < data.evals.length; i++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]); + } + if (!bindingDef.renderOnNullValue) { + if (data.x === null) { + el.style.visibility = "hidden"; + return; + } else { + el.style.visibility = "inherit"; + } + } + if (!elementData(el, "initialized")) { + initSizing(el); + + elementData(el, "initialized", true); + if (bindingDef.initialize) { + var result = bindingDef.initialize(el, el.offsetWidth, + el.offsetHeight); + elementData(el, "init_result", result); + } + } + bindingDef.renderValue(el, data.x, elementData(el, "init_result")); + evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]); + }; + + // Only override resize if bindingDef implements it + if (bindingDef.resize) { + shinyBinding.resize = function(el, width, height) { + // Shiny can call resize before initialize/renderValue have been + // called, which doesn't make sense for widgets. + if (elementData(el, "initialized")) { + bindingDef.resize(el, width, height, elementData(el, "init_result")); + } + }; + } + + Shiny.outputBindings.register(shinyBinding, bindingDef.name); + } + }; + + var scheduleStaticRenderTimerId = null; + function scheduleStaticRender() { + if (!scheduleStaticRenderTimerId) { + scheduleStaticRenderTimerId = setTimeout(function() { + scheduleStaticRenderTimerId = null; + window.HTMLWidgets.staticRender(); + }, 1); + } + } + + // Render static widgets after the document finishes loading + // Statically render all elements that are of this widget's class + window.HTMLWidgets.staticRender = function() { + var bindings = window.HTMLWidgets.widgets || []; + forEach(bindings, function(binding) { + var matches = binding.find(document.documentElement); + forEach(matches, function(el) { + var sizeObj = initSizing(el, binding); + + if (hasClass(el, "html-widget-static-bound")) + return; + el.className = el.className + " html-widget-static-bound"; + + var initResult; + if (binding.initialize) { + initResult = binding.initialize(el, + sizeObj ? sizeObj.getWidth() : el.offsetWidth, + sizeObj ? sizeObj.getHeight() : el.offsetHeight + ); + elementData(el, "init_result", initResult); + } + + if (binding.resize) { + var lastSize = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + var resizeHandler = function(e) { + var size = { + w: sizeObj ? sizeObj.getWidth() : el.offsetWidth, + h: sizeObj ? sizeObj.getHeight() : el.offsetHeight + }; + if (size.w === 0 && size.h === 0) + return; + if (size.w === lastSize.w && size.h === lastSize.h) + return; + lastSize = size; + binding.resize(el, size.w, size.h, initResult); + }; + + on(window, "resize", resizeHandler); + + // This is needed for cases where we're running in a Shiny + // app, but the widget itself is not a Shiny output, but + // rather a simple static widget. One example of this is + // an rmarkdown document that has runtime:shiny and widget + // that isn't in a render function. Shiny only knows to + // call resize handlers for Shiny outputs, not for static + // widgets, so we do it ourselves. + if (window.jQuery) { + window.jQuery(document).on( + "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets", + resizeHandler + ); + window.jQuery(document).on( + "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets", + resizeHandler + ); + } + + // This is needed for the specific case of ioslides, which + // flips slides between display:none and display:block. + // Ideally we would not have to have ioslide-specific code + // here, but rather have ioslides raise a generic event, + // but the rmarkdown package just went to CRAN so the + // window to getting that fixed may be long. + if (window.addEventListener) { + // It's OK to limit this to window.addEventListener + // browsers because ioslides itself only supports + // such browsers. + on(document, "slideenter", resizeHandler); + on(document, "slideleave", resizeHandler); + } + } + + var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']"); + if (scriptData) { + var data = JSON.parse(scriptData.textContent || scriptData.text); + // Resolve strings marked as javascript literals to objects + if (!(data.evals instanceof Array)) data.evals = [data.evals]; + for (var k = 0; data.evals && k < data.evals.length; k++) { + window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]); + } + binding.renderValue(el, data.x, initResult); + evalAndRun(data.jsHooks.render, initResult, [el, data.x]); + } + }); + }); + + invokePostRenderHandlers(); + } + + + function has_jQuery3() { + if (!window.jQuery) { + return false; + } + var $version = window.jQuery.fn.jquery; + var $major_version = parseInt($version.split(".")[0]); + return $major_version >= 3; + } + + /* + / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's + / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now + / really means $(setTimeout(fn)). + / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous + / + / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny + / one tick later than it did before, which means staticRender() is + / called renderValue() earlier than (advanced) widget authors might be expecting. + / https://github.com/rstudio/shiny/issues/2630 + / + / For a concrete example, leaflet has some methods (e.g., updateBounds) + / which reference Shiny methods registered in initShiny (e.g., setInputValue). + / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to + / delay execution of those methods (until Shiny methods are ready) + / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268 + / + / Ideally widget authors wouldn't need to use this setTimeout() hack that + / leaflet uses to call Shiny methods on a staticRender(). In the long run, + / the logic initShiny should be broken up so that method registration happens + / right away, but binding happens later. + */ + function maybeStaticRenderLater() { + if (shinyMode && has_jQuery3()) { + window.jQuery(window.HTMLWidgets.staticRender); + } else { + window.HTMLWidgets.staticRender(); + } + } + + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", function() { + document.removeEventListener("DOMContentLoaded", arguments.callee, false); + maybeStaticRenderLater(); + }, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", function() { + if (document.readyState === "complete") { + document.detachEvent("onreadystatechange", arguments.callee); + maybeStaticRenderLater(); + } + }); + } + + + window.HTMLWidgets.getAttachmentUrl = function(depname, key) { + // If no key, default to the first item + if (typeof(key) === "undefined") + key = 1; + + var link = document.getElementById(depname + "-" + key + "-attachment"); + if (!link) { + throw new Error("Attachment " + depname + "/" + key + " not found in document"); + } + return link.getAttribute("href"); + }; + + window.HTMLWidgets.dataframeToD3 = function(df) { + var names = []; + var length; + for (var name in df) { + if (df.hasOwnProperty(name)) + names.push(name); + if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") { + throw new Error("All fields must be arrays"); + } else if (typeof(length) !== "undefined" && length !== df[name].length) { + throw new Error("All fields must be arrays of the same length"); + } + length = df[name].length; + } + var results = []; + var item; + for (var row = 0; row < length; row++) { + item = {}; + for (var col = 0; col < names.length; col++) { + item[names[col]] = df[names[col]][row]; + } + results.push(item); + } + return results; + }; + + window.HTMLWidgets.transposeArray2D = function(array) { + if (array.length === 0) return array; + var newArray = array[0].map(function(col, i) { + return array.map(function(row) { + return row[i] + }) + }); + return newArray; + }; + // Split value at splitChar, but allow splitChar to be escaped + // using escapeChar. Any other characters escaped by escapeChar + // will be included as usual (including escapeChar itself). + function splitWithEscape(value, splitChar, escapeChar) { + var results = []; + var escapeMode = false; + var currentResult = ""; + for (var pos = 0; pos < value.length; pos++) { + if (!escapeMode) { + if (value[pos] === splitChar) { + results.push(currentResult); + currentResult = ""; + } else if (value[pos] === escapeChar) { + escapeMode = true; + } else { + currentResult += value[pos]; + } + } else { + currentResult += value[pos]; + escapeMode = false; + } + } + if (currentResult !== "") { + results.push(currentResult); + } + return results; + } + // Function authored by Yihui/JJ Allaire + window.HTMLWidgets.evaluateStringMember = function(o, member) { + var parts = splitWithEscape(member, '.', '\\'); + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + // part may be a character or 'numeric' member name + if (o !== null && typeof o === "object" && part in o) { + if (i == (l - 1)) { // if we are at the end of the line then evalulate + if (typeof o[part] === "string") + o[part] = tryEval(o[part]); + } else { // otherwise continue to next embedded object + o = o[part]; + } + } + } + }; + + // Retrieve the HTMLWidget instance (i.e. the return value of an + // HTMLWidget binding's initialize() or factory() function) + // associated with an element, or null if none. + window.HTMLWidgets.getInstance = function(el) { + return elementData(el, "init_result"); + }; + + // Finds the first element in the scope that matches the selector, + // and returns the HTMLWidget instance (i.e. the return value of + // an HTMLWidget binding's initialize() or factory() function) + // associated with that element, if any. If no element matches the + // selector, or the first matching element has no HTMLWidget + // instance associated with it, then null is returned. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.find = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var el = scope.querySelector(selector); + if (el === null) { + return null; + } else { + return window.HTMLWidgets.getInstance(el); + } + }; + + // Finds all elements in the scope that match the selector, and + // returns the HTMLWidget instances (i.e. the return values of + // an HTMLWidget binding's initialize() or factory() function) + // associated with the elements, in an array. If elements that + // match the selector don't have an associated HTMLWidget + // instance, the returned array will contain nulls. + // + // The scope argument is optional, and defaults to window.document. + window.HTMLWidgets.findAll = function(scope, selector) { + if (arguments.length == 1) { + selector = scope; + scope = document; + } + + var nodes = scope.querySelectorAll(selector); + var results = []; + for (var i = 0; i < nodes.length; i++) { + results.push(window.HTMLWidgets.getInstance(nodes[i])); + } + return results; + }; + + var postRenderHandlers = []; + function invokePostRenderHandlers() { + while (postRenderHandlers.length) { + var handler = postRenderHandlers.shift(); + if (handler) { + handler(); + } + } + } + + // Register the given callback function to be invoked after the + // next time static widgets are rendered. + window.HTMLWidgets.addPostRenderHandler = function(callback) { + postRenderHandlers.push(callback); + }; + + // Takes a new-style instance-bound definition, and returns an + // old-style class-bound definition. This saves us from having + // to rewrite all the logic in this file to accomodate both + // types of definitions. + function createLegacyDefinitionAdapter(defn) { + var result = { + name: defn.name, + type: defn.type, + initialize: function(el, width, height) { + return defn.factory(el, width, height); + }, + renderValue: function(el, x, instance) { + return instance.renderValue(x); + }, + resize: function(el, width, height, instance) { + return instance.resize(width, height); + } + }; + + if (defn.find) + result.find = defn.find; + if (defn.renderError) + result.renderError = defn.renderError; + if (defn.clearError) + result.clearError = defn.clearError; + + return result; + } +})(); + diff --git a/docs/site_libs/jquery-1.11.3/jquery.min.js b/docs/site_libs/jquery-1.11.3/jquery.min.js new file mode 100644 index 00000000..0f60b7bd --- /dev/null +++ b/docs/site_libs/jquery-1.11.3/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
      a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
      ","
      "],area:[1,"",""],param:[1,"",""],thead:[1,"","
      "],tr:[2,"","
      "],col:[2,"","
      "],td:[3,"","
      "],_default:k.htmlSerialize?[0,"",""]:[1,"X
      ","
      "]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("