+
+
Think about the last time you had a splitting headache and needed some quick relief. Which bottle did you reach for? Tylenol or Advil? Why? Maybe you think of yourself as a “Tylenol person” or an “Advil person” because one of these has worked for you before. Or maybe one always upsets your stomach. The point is that not everyone experiences the same pain relief from one pill. Some people prefer Tylenol and others Advil, but nobody quite knows why.
The same is true of psychological treatments—they don’t work the same way for all people. People differ in how they respond to treatments for depression, anxiety, addiction, and so forth. The lingo in the field is that there are individual differences in treatment effectiveness. Why? Because, to state the obvious, no two people are exactly alike. And that fact poses a problem for the study of these treatments. Researchers test psychological treatments the same way they test drugs like Tylenol and Advil—using randomized controlled trials (RCTs). People are assigned at random to either one group, which receives a treatment, or another group, which does not. RCTs are an excellent way to assess the differences between the groups on average. The group difference indicates how well the treatment works. The problem is that researchers tend to treat people who differ from their group’s average as mere statistical fluctuations—“noise” in the signal.
@@ -28,23 +34,23 @@ The drawback of group-to-group comparisons is that they hide person-to-person di
How do we learn for whom psychological treatments will work? There are three main things we need to know:
-# 1) How does the treatment work?
+## 1) How does the treatment work?
At this point, there is strong evidence that Tylenol is an effective painkiller. But, even after decades of research, we still don’t fully understand how Tylenol relieves pain. Similarly, though we know that many psychological treatments are effective (at least for some people), we do not know how these treatments work. For example, researchers don’t know which parts of the brain are changed by most treatments. If we knew more specifics about how a treatment worked, we could improve it. We could focus our efforts on the parts of the treatment that make people better and remove the parts that don’t seem as important. And here’s the bonus: If we knew how treatments worked, that would help us learn for whom they work. Imagine we knew that a treatment reduced depression by decreasing self-criticism. In other words, a reduction in self-criticism is the one and only active ingredient in this treatment. If so, then people who criticize themselves a lot would be good candidates to benefit most from this treatment.
-# 2) What are the unique causes of the problem for a given person?
+## 2) What are the unique causes of the problem for a given person?
To predict whether someone would benefit from a given treatment, we need to know more about the special factors underlying that person’s problem. In terms of pain, Tylenol is usually the better option for headache pain, and Advil is a good bet for inflammation. Similarly, a psychological treatment will work for a given person only if it addresses whatever caused the problem in the first place. Consider two people who both experience severe anxiety, but for different reasons. If genetic factors cause one person’s anxiety while past trauma is the main source of the other person’s anxiety, then these two individuals will likely need different types of treatment.
-# 3) How does the treatment mesh with a person’s unique characteristics?
+## 3) How does the treatment mesh with a person’s unique characteristics?
Like all drugs, Tylenol and Advil have side effects. And it turns out that they have different side effects depending on whether somebody is at risk for heart disease. So, people who have experienced a heart attack, for example, must carefully choose which pill to take when they have a headache. Similarly, whether or not a psychological treatment will work for somebody might depend on that person’s age, gender, or life history, to name just a few examples. The success of many treatments also depends on how severe a person’s problem is to begin with. Consider again the example of a treatment for depression that works on average for a group of people. Perhaps this treatment works best for people who are severely depressed because it focuses on a symptom that is more common in those people. A different treatment, which also works on average, might consistently decrease depression in mildly depressed people but not work at all for severely depressed people.
-# The bottom line
+## The bottom line
With answers to these three questions, researchers can begin to tailor psychological treatments to the unique needs of different people. We know that a given treatment will not work, at least not equally well, for every person. But being able to predict at the outset who will benefit and who won’t could save a lot of time and money. Rather than treating individual differences as “noise,” we can use them to glean potentially important information. If we can better understand why some people benefit from treatment while others don’t, we can make treatments more effective for more people. Eventually, this will allow more people to live healthier lives.
->*Note*. I originally wrote this piece for Psychology Today. See the original post [here](https://www.psychologytoday.com/us/blog/the-motivated-brain/201712/one-size-rarely-fits-all){target="_blank"}.
\ No newline at end of file
+>*Note*. I originally wrote this piece for Psychology Today. See the original post [here](https://www.psychologytoday.com/us/blog/the-motivated-brain/201712/one-size-rarely-fits-all).
\ No newline at end of file
diff --git a/content/blog/2017-12-01-one-size-rarely-fits-all/index.markdown b/content/blog/2017-12-01-one-size-rarely-fits-all/index.markdown
new file mode 100644
index 0000000..2c419a4
--- /dev/null
+++ b/content/blog/2017-12-01-one-size-rarely-fits-all/index.markdown
@@ -0,0 +1,56 @@
+---
+title: One Size Rarely Fits All
+layout: single
+author: Brendan Cullen
+date: '2017-12-01'
+slug: []
+categories:
+tags:
+ - precision-medicine
+ - health
+ - psychology
+subtitle: ''
+summary: 'A case for a precision medicine approach to behavioral health in psychology'
+authors: []
+lastmod: ''
+featured: no
+image:
+ caption: 'Source: Shutterstock / HelloRF Zcool'
+ focal_point: ''
+ preview_only: FALSE
+projects: []
+---
+
+
+
+
+
+
+Think about the last time you had a splitting headache and needed some quick relief. Which bottle did you reach for? Tylenol or Advil? Why? Maybe you think of yourself as a “Tylenol person” or an “Advil person” because one of these has worked for you before. Or maybe one always upsets your stomach. The point is that not everyone experiences the same pain relief from one pill. Some people prefer Tylenol and others Advil, but nobody quite knows why.
+
+The same is true of psychological treatments—they don’t work the same way for all people. People differ in how they respond to treatments for depression, anxiety, addiction, and so forth. The lingo in the field is that there are individual differences in treatment effectiveness. Why? Because, to state the obvious, no two people are exactly alike. And that fact poses a problem for the study of these treatments. Researchers test psychological treatments the same way they test drugs like Tylenol and Advil—using randomized controlled trials (RCTs). People are assigned at random to either one group, which receives a treatment, or another group, which does not. RCTs are an excellent way to assess the differences between the groups on average. The group difference indicates how well the treatment works. The problem is that researchers tend to treat people who differ from their group’s average as mere statistical fluctuations—“noise” in the signal.
+
+The drawback of group-to-group comparisons is that they hide person-to-person differences that may be important. For example, even when one group does a lot better than another on average, there may still be many people in the first group who do not improve at all. Or maybe some people in the first group get worse even though their group got better overall. Instead of only thinking at the “group” level, we need to pay more attention to person-to-person differences. This will help us learn why treatments work only for some individuals and not others.
+
+How do we learn for whom psychological treatments will work? There are three main things we need to know:
+
+## 1) How does the treatment work?
+
+At this point, there is strong evidence that Tylenol is an effective painkiller. But, even after decades of research, we still don’t fully understand how Tylenol relieves pain. Similarly, though we know that many psychological treatments are effective (at least for some people), we do not know how these treatments work. For example, researchers don’t know which parts of the brain are changed by most treatments. If we knew more specifics about how a treatment worked, we could improve it. We could focus our efforts on the parts of the treatment that make people better and remove the parts that don’t seem as important. And here’s the bonus: If we knew how treatments worked, that would help us learn for whom they work. Imagine we knew that a treatment reduced depression by decreasing self-criticism. In other words, a reduction in self-criticism is the one and only active ingredient in this treatment. If so, then people who criticize themselves a lot would be good candidates to benefit most from this treatment.
+
+
+## 2) What are the unique causes of the problem for a given person?
+
+To predict whether someone would benefit from a given treatment, we need to know more about the special factors underlying that person’s problem. In terms of pain, Tylenol is usually the better option for headache pain, and Advil is a good bet for inflammation. Similarly, a psychological treatment will work for a given person only if it addresses whatever caused the problem in the first place. Consider two people who both experience severe anxiety, but for different reasons. If genetic factors cause one person’s anxiety while past trauma is the main source of the other person’s anxiety, then these two individuals will likely need different types of treatment.
+
+
+## 3) How does the treatment mesh with a person’s unique characteristics?
+
+Like all drugs, Tylenol and Advil have side effects. And it turns out that they have different side effects depending on whether somebody is at risk for heart disease. So, people who have experienced a heart attack, for example, must carefully choose which pill to take when they have a headache. Similarly, whether or not a psychological treatment will work for somebody might depend on that person’s age, gender, or life history, to name just a few examples. The success of many treatments also depends on how severe a person’s problem is to begin with. Consider again the example of a treatment for depression that works on average for a group of people. Perhaps this treatment works best for people who are severely depressed because it focuses on a symptom that is more common in those people. A different treatment, which also works on average, might consistently decrease depression in mildly depressed people but not work at all for severely depressed people.
+
+
+## The bottom line
+
+With answers to these three questions, researchers can begin to tailor psychological treatments to the unique needs of different people. We know that a given treatment will not work, at least not equally well, for every person. But being able to predict at the outset who will benefit and who won’t could save a lot of time and money. Rather than treating individual differences as “noise,” we can use them to glean potentially important information. If we can better understand why some people benefit from treatment while others don’t, we can make treatments more effective for more people. Eventually, this will allow more people to live healthier lives.
+
+>*Note*. I originally wrote this piece for Psychology Today. See the original post [here](https://www.psychologytoday.com/us/blog/the-motivated-brain/201712/one-size-rarely-fits-all).
diff --git a/content/blog/2017-12-01-one-size-rarely-fits-all/index_files/header-attrs/header-attrs.js b/content/blog/2017-12-01-one-size-rarely-fits-all/index_files/header-attrs/header-attrs.js
new file mode 100644
index 0000000..dd57d92
--- /dev/null
+++ b/content/blog/2017-12-01-one-size-rarely-fits-all/index_files/header-attrs/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/content/blog/2020-03-08-data-science-training-needs-in-grad-school/Trainingneedssurvey.xlsx b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/Trainingneedssurvey.xlsx
new file mode 100644
index 0000000..d6aa107
Binary files /dev/null and b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/Trainingneedssurvey.xlsx differ
diff --git a/content/post/2020-03-08-data-science-training-needs-in-grad-school/featured.jpg b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/featured.jpg
similarity index 100%
rename from content/post/2020-03-08-data-science-training-needs-in-grad-school/featured.jpg
rename to content/blog/2020-03-08-data-science-training-needs-in-grad-school/featured.jpg
diff --git a/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.Rmarkdown b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.Rmarkdown
new file mode 100644
index 0000000..0642c01
--- /dev/null
+++ b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.Rmarkdown
@@ -0,0 +1,171 @@
+---
+title: Data Science Training in Psychology
+layout: single
+author: Brendan Cullen
+date: '2020-03-08'
+slug: []
+categories: []
+tags:
+ - data science
+ - education
+ - R
+ - grad school
+subtitle: ''
+summary: 'Reflections on the importance of data science training in psychology and how we might close training gaps for grad students.'
+authors: []
+lastmod: ''
+featured: no
+image:
+ caption: 'Photo by Emile Perron on Unsplash'
+ focal_point: ''
+ preview_only: no
+projects: []
+---
+
+
+
+
+
+
+Psychology is generally considered a "soft" science, on the opposite end of the spectrum from the "hard" sciences of physics, chemistry, and biology. This often creates a misconception that psychology is somehow not as quantitative, computational, or rigorous, methodologically. To the contrary, psychology is in fact very "hard" (some might even say ["the hardest"](https://thehardestscience.com/2009/03/14/making-progress-in-the-hardest-science/)). Why? Because explaining human cognition and behavior is really difficult. People do not think and behave in predictable and consistent ways like atoms and molecules.
+
+Indeed, the combination of random variation ("noise") in how we humans respond to our environment on an given day/hour/minute, combined with the inherent challenge of proper sampling, reliable measurement and accurate model building makes data analysis for a psychologist no easy feat. Explaining variance in psychological data has required centuries of refining statistical methods and computational tools. Fortunately, today's scientists have access to open-source software like R and Python that have *vastly* enhanced our ability to work with data in a way that is more transparent and reproducible. As a result, the teaching of these tools is becoming increasingly more common in psychology graduate programs (and many other fields), particularly in statistics classes.
+
+***
+
+## Graduate statistics
+
+The Department of Psychology at the University of Oregon requires first-year graduate students to take a 3-course series of classes on statistics and data analysis. (You can access the materials for these classes [here.](https://github.com/uopsych)) As I'm sure used to be the case in psychology departments across many universities, the labs for these classes were originally taught in SPSS. However, thanks to the efforts of some hard-working graduate teaching assistants who served as lab instructors at the time, the labs eventually transitioned to being taught entirely in R.
+
+While learning R in first-year grad stats has immense benefits, it is also really challenging. In addition to grappling with the dense conceptual material, learning a programming language and using it to do statistics felt really daunting since I had very little programming background before graduate school. And the reality is, given that many (myself included) tend to experience a large learning curve with programming, combined with the already hefty gradstats curriculum, there just isn't space in these classes to teach students much beyond the basics of R.
+
+***
+
+## Training needs
+
+But the way things seem to be moving, it's becoming more common for many students to need more general data science skills in grad school. Current psychology grad students at UO (n = 28) were recently surveyed about the degree to which they perceive they will need different data science-related skills for their desired careers and how much training in those skills is available at UO to their knowledge. Specifically, they were asked,
+
+* On a scale of 0 ("Not at all") to 4 ("Essential"), how much do you NEED this skill for your desired career?
+
+* On a scale of 0 ("Not at all") to 4 ("Complete"), how much training is PROVIDED in this skill at your institution?
+
+
+I created the plot below to visualize how much students report they need these skills compared to how much training they feel they already have.
+
+```{r echo=FALSE, message = FALSE, warning = FALSE}
+library(tidyverse)
+library(gdata)
+library(janitor)
+library(colorblindr)
+
+# import raw data
+data_raw <- rio::import("Trainingneedssurvey.xlsx", sheet = 2 ) %>%
+ clean_names() %>%
+ rename(skill = x1) %>%
+ #mapvalues(skill, from = "Analysis Neuroimaging", to = "Neuroimaging Analysis")
+ mutate(skill = str_to_title(skill))
+
+# fix typos
+data_raw$skill <-as.factor(recode(data_raw$skill, "Analysis Neuroimaging"="Neuroimaging Analysis", "Research Ethic"= "Research Ethics"))
+
+# means
+data_m <- data_raw %>%
+ select(skill, need_m, have_m) %>%
+ gather(c(need_m,have_m), key = need_have, value = mean) %>%
+ mutate(need_have = factor(need_have,
+ labels = c("Have", "Need")))
+# standard errors
+data_se <- data_raw %>%
+ select(skill, need_se, have_se) %>%
+ gather(c(need_se,have_se), key = need_have, value = se) %>%
+ mutate(need_have = factor(need_have,
+ labels = c("Have", "Need")))
+
+# join data
+data_tidy <- left_join(data_m, data_se)
+
+data_diff <- data_raw %>%
+ select(skill, need_m, have_m) %>%
+ mutate(diff = need_m - have_m)
+```
+
+```{r echo=FALSE, warning=FALSE, fig.width=15, fig.height=10}
+data_tidy %>%
+ ggplot(aes(fct_reorder2(skill, need_have, desc(mean)), mean)) +
+ expand_limits(y = c(0, 4)) +
+ coord_flip() +
+ geom_line(aes(group = skill), linetype = 3, color = "gray40") +
+ geom_errorbar(aes(
+ ymin = mean - se,
+ ymax = mean + se,
+ group = need_have
+ ),
+ alpha = 0.25) +
+ geom_point(aes(color = need_have), size = 7) +
+ theme_minimal(base_size = 17) +
+ scale_color_manual(values = c("#ABC7C4", "#609298")) +
+ scale_y_continuous(
+ labels = c(
+ "0 \n(Not at all)",
+ "1 \n(A little)",
+ "2 \n(Some)",
+ "3 \n(Very much)",
+ "4 \n(Essential/\nComplete)"
+ )
+ ) +
+ labs(
+ x = "",
+ y = "\nMean Response",
+ title = "Data science training needs for UO psychology doctoral students",
+ caption = "Error bars represent standard error of the mean."
+ ) +
+ theme(
+ panel.grid.minor = element_blank(),
+ legend.title = element_blank(),
+ legend.key.size = unit(1, "cm"),
+ legend.direction = "horizontal",
+ legend.position = c(0.84, 0.07),
+ legend.box.background = element_rect(fill = "white"),
+ legend.background = element_rect(color = "#ABC7C4"),
+ legend.text = element_text(size = 15)
+ )
+```
+
+Interestingly, the top two skills that students reported needing the most on average for their careers are data visualization and data wrangling. Fortunately, this was the first year (to my knowledge) that [PSY611](https://uopsych.github.io/psy611/), the first course in the gradstats sequence, included entire labs devoted to data visualization and data wrangling.
+
+Among other crucial research skills like study design, data collection, and research ethics, the other most coveted technical skill seems to be *programming*. In fact, general programming skills seems to be where there is currently the biggest gap in training in our department. The graph below shows skills ranked in descending order by how large the gap is between how much training in those skills students need and how much they currently have.
+
+```{r echo=FALSE, warning=FALSE, fig.width=15, fig.height=10}
+data_diff %>%
+ ggplot(aes(x = fct_reorder(skill, diff), y = diff)) +
+ geom_col(alpha = 0.8, color = "#609298") +
+ coord_flip() +
+ geom_hline(yintercept = 0,
+ size = 1,
+ color = "black") +
+ labs(
+ x = "",
+ y = "Training Gap (Need - Have)",
+ title = "Perceived gaps in data science training from current UO psychology doctoral students"
+ ) +
+ theme_minimal(base_size = 17) +
+ theme(panel.grid.minor = element_blank(),
+ plot.caption = element_text(size = 17, hjust = 0))
+```
+
+On the whole, it seems that that there are bigger training gaps for more general data science skills (e.g., programming in R and Python, data wrangling, data visualization). In contrast, the smallest gaps exist for more specialized skills like advanced statistics (e.g., computational modeling, network analysis, structural equation modeling) -- likely because our department has an entire class devoted to each of these topics.
+
+***
+## Learning Resources
+
+For the most part, it seems that grad students in our department want more training in general data science skills above and beyond the training they are currently receiving through coursework. Often what this means is that grad students end up teaching themselves (and each other) these skills. Some of my peers have made really incredible tutorials on new tools and methodologies they've recently learned. Sometimes students also attend specialized methods workshops and take detailed notes that could greatly benefit others who want to learn the same kind of methods.
+
+What I would love to see is a central, searchable repository of data science resources at UO that will house these student-created tutorials, workshop notes, and other data science products (e.g. R packages, shiny apps, etc.) that will make it easier for folks (both within our department and beyond) to find these resources.
+
+***
+
+## A final thought
+
+Reflecting on all this has brought home a thought that I think is worth sharing -- as grad students, one of the best resources we have access to during our time in grad school is *each other*. Personally, I have learned so much over the years from my [fellow lab members](https://sanlab.uoregon.edu/people/). Without them, I would not have conquered my fear of Github or felt inspired to learn more about R and other programming languages. Perhaps the most impactful benefit I've received from them, though, is their encouragement -- and that, in particular, is something I hope to pay forward as much as possible.
+
+We all enter grad school with different backgrounds and skill sets, and in so many situations the combination of our different strengths can lead to mutual benefit. So why not help each other out?
diff --git a/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.markdown b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.markdown
new file mode 100644
index 0000000..95d07ed
--- /dev/null
+++ b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index.markdown
@@ -0,0 +1,80 @@
+---
+title: Data Science Training in Psychology
+layout: single
+author: Brendan Cullen
+date: '2020-03-08'
+slug: []
+categories: []
+tags:
+ - data science
+ - education
+ - R
+ - grad school
+subtitle: ''
+summary: 'Reflections on the importance of data science training in psychology and how we might close training gaps for grad students.'
+authors: []
+lastmod: ''
+featured: no
+image:
+ caption: 'Photo by Emile Perron on Unsplash'
+ focal_point: ''
+ preview_only: no
+projects: []
+---
+
+
+
+
+
+
+Psychology is generally considered a "soft" science, on the opposite end of the spectrum from the "hard" sciences of physics, chemistry, and biology. This often creates a misconception that psychology is somehow not as quantitative, computational, or rigorous, methodologically. To the contrary, psychology is in fact very "hard" (some might even say ["the hardest"](https://thehardestscience.com/2009/03/14/making-progress-in-the-hardest-science/)). Why? Because explaining human cognition and behavior is really difficult. People do not think and behave in predictable and consistent ways like atoms and molecules.
+
+Indeed, the combination of random variation ("noise") in how we humans respond to our environment on an given day/hour/minute, combined with the inherent challenge of proper sampling, reliable measurement and accurate model building makes data analysis for a psychologist no easy feat. Explaining variance in psychological data has required centuries of refining statistical methods and computational tools. Fortunately, today's scientists have access to open-source software like R and Python that have *vastly* enhanced our ability to work with data in a way that is more transparent and reproducible. As a result, the teaching of these tools is becoming increasingly more common in psychology graduate programs (and many other fields), particularly in statistics classes.
+
+***
+
+## Graduate statistics
+
+The Department of Psychology at the University of Oregon requires first-year graduate students to take a 3-course series of classes on statistics and data analysis. (You can access the materials for these classes [here.](https://github.com/uopsych)) As I'm sure used to be the case in psychology departments across many universities, the labs for these classes were originally taught in SPSS. However, thanks to the efforts of some hard-working graduate teaching assistants who served as lab instructors at the time, the labs eventually transitioned to being taught entirely in R.
+
+While learning R in first-year grad stats has immense benefits, it is also really challenging. In addition to grappling with the dense conceptual material, learning a programming language and using it to do statistics felt really daunting since I had very little programming background before graduate school. And the reality is, given that many (myself included) tend to experience a large learning curve with programming, combined with the already hefty gradstats curriculum, there just isn't space in these classes to teach students much beyond the basics of R.
+
+***
+
+## Training needs
+
+But the way things seem to be moving, it's becoming more common for many students to need more general data science skills in grad school. Current psychology grad students at UO (n = 28) were recently surveyed about the degree to which they perceive they will need different data science-related skills for their desired careers and how much training in those skills is available at UO to their knowledge. Specifically, they were asked,
+
+* On a scale of 0 ("Not at all") to 4 ("Essential"), how much do you NEED this skill for your desired career?
+
+* On a scale of 0 ("Not at all") to 4 ("Complete"), how much training is PROVIDED in this skill at your institution?
+
+
+I created the plot below to visualize how much students report they need these skills compared to how much training they feel they already have.
+
+
+
+
+
+Interestingly, the top two skills that students reported needing the most on average for their careers are data visualization and data wrangling. Fortunately, this was the first year (to my knowledge) that [PSY611](https://uopsych.github.io/psy611/), the first course in the gradstats sequence, included entire labs devoted to data visualization and data wrangling.
+
+Among other crucial research skills like study design, data collection, and research ethics, the other most coveted technical skill seems to be *programming*. In fact, general programming skills seems to be where there is currently the biggest gap in training in our department. The graph below shows skills ranked in descending order by how large the gap is between how much training in those skills students need and how much they currently have.
+
+
+
+On the whole, it seems that that there are bigger training gaps for more general data science skills (e.g., programming in R and Python, data wrangling, data visualization). In contrast, the smallest gaps exist for more specialized skills like advanced statistics (e.g., computational modeling, network analysis, structural equation modeling) -- likely because our department has an entire class devoted to each of these topics.
+
+***
+## Learning Resources
+
+For the most part, it seems that grad students in our department want more training in general data science skills above and beyond the training they are currently receiving through coursework. Often what this means is that grad students end up teaching themselves (and each other) these skills. Some of my peers have made really incredible tutorials on new tools and methodologies they've recently learned. Sometimes students also attend specialized methods workshops and take detailed notes that could greatly benefit others who want to learn the same kind of methods.
+
+What I would love to see is a central, searchable repository of data science resources at UO that will house these student-created tutorials, workshop notes, and other data science products (e.g. R packages, shiny apps, etc.) that will make it easier for folks (both within our department and beyond) to find these resources.
+
+***
+
+## A final thought
+
+Reflecting on all this has brought home a thought that I think is worth sharing -- as grad students, one of the best resources we have access to during our time in grad school is *each other*. Personally, I have learned so much over the years from my [fellow lab members](https://sanlab.uoregon.edu/people/). Without them, I would not have conquered my fear of Github or felt inspired to learn more about R and other programming languages. Perhaps the most impactful benefit I've received from them, though, is their encouragement -- and that, in particular, is something I hope to pay forward as much as possible.
+
+We all enter grad school with different backgrounds and skill sets, and in so many situations the combination of our different strengths can lead to mutual benefit. So why not help each other out?
diff --git a/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-2-1.png b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-2-1.png
new file mode 100644
index 0000000..3e1ed62
Binary files /dev/null and b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-2-1.png differ
diff --git a/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-3-1.png b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-3-1.png
new file mode 100644
index 0000000..3a7eb01
Binary files /dev/null and b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/figure-html/unnamed-chunk-3-1.png differ
diff --git a/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/header-attrs/header-attrs.js b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/header-attrs/header-attrs.js
new file mode 100644
index 0000000..dd57d92
--- /dev/null
+++ b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/index_files/header-attrs/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/content/post/2020-03-08-data-science-training-needs-in-grad-school/training_dotplot_se.png b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/training_dotplot_se.png
similarity index 100%
rename from content/post/2020-03-08-data-science-training-needs-in-grad-school/training_dotplot_se.png
rename to content/blog/2020-03-08-data-science-training-needs-in-grad-school/training_dotplot_se.png
diff --git a/content/post/2020-03-08-data-science-training-needs-in-grad-school/training_gaps.png b/content/blog/2020-03-08-data-science-training-needs-in-grad-school/training_gaps.png
similarity index 100%
rename from content/post/2020-03-08-data-science-training-needs-in-grad-school/training_gaps.png
rename to content/blog/2020-03-08-data-science-training-needs-in-grad-school/training_gaps.png
diff --git a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/data_dictionary.csv b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/data_dictionary.csv
similarity index 100%
rename from content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/data_dictionary.csv
rename to content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/data_dictionary.csv
diff --git a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/featured.jpg b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/featured.jpg
similarity index 100%
rename from content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/featured.jpg
rename to content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/featured.jpg
diff --git a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmd b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmarkdown
similarity index 83%
rename from content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmd
rename to content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmarkdown
index 837c75d..11eb899 100644
--- a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmd
+++ b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.Rmarkdown
@@ -1,35 +1,38 @@
---
-title: 'Tidymodels: Decision Tree Learning in R'
-author: Cianna Bedford-Petersen, Christopher Loan & Brendan Cullen
+title: 'Decision Tree Learning in R'
+layout: single
+author: Brendan Cullen, Cianna Bedford-Petersen & Christopher Loan
date: '2020-06-02'
slug: []
categories: []
tags: []
-subtitle: 'Cianna Bedford-Petersen, Christopher Loan & Brendan Cullen'
-summary: 'An overview and worked example of tree-based machine learning methods in R using `tidymodels`'
+subtitle: ''
+summary: 'An overview and worked example of tree-based machine learning methods in R using tidymodels'
authors: []
-lastmod: '2020-06-02T10:57:23-07:00'
+lastmod: ''
featured: no
image:
caption: 'Image by Ilona Ilyés from Pixabay'
focal_point: ''
preview_only: FALSE
projects: []
-disable_codefolding: false
-codefolding_show: "show"
-codefolding_nobutton: false
---
-RStudio has recently released a cohesive suite of packages for modelling and machine learning, called `{tidymodels}`. The successor to Max Kuhn’s `{caret}` package, `{tidymodels}` allows for a tidy approach to your data from start to finish. We’re going to walk through the basics for getting off the ground with `{tidymodels}` and demonstrate its application to three different tree-based methods for predicting student test scores. For further information about the package, you can visit https://www.tidymodels.org/.
+
+
+
+
-# Setup
+RStudio has recently released a cohesive suite of packages for modelling and machine learning, called tidymodels. The successor to Max Kuhn’s caret package, tidymodels allows for a tidy approach to your data from start to finish. We’re going to walk through the basics for getting off the ground with tidymodels and demonstrate its application to three different tree-based methods for predicting student test scores. For further information about the package, you can visit https://www.tidymodels.org/.
+
+## Setup
```{r echo=FALSE}
options(scipen = 17)
```
-Load both the `{tidyverse}` and `{tidymodels}` packages into your environment. We’ll also load in the `{skimr}` package to help us with some descriptives for our data and a host of other packages that will be required to run our machine learning models.
+Load both the tidyverse and tidymodels packages into your environment. We’ll also load in the skimr package to help us with some descriptives for our data and a host of other packages that will be required to run our machine learning models.
```{r message=FALSE}
library(tidymodels)
@@ -40,7 +43,7 @@ library(future) # parallel processing & decrease computation time
library(xgboost) # boosted trees
```
-# Import the data
+## Import the data
We use simulated data which approximates reading and math scores for ~189,000 3rd-8th grade students in Oregon public schools see [this Kaggle page](https://www.kaggle.com/c/edld-654-spring-2020) for details. For the purpose of demonstration, we’ll be sampling 1% of the data with `sample_frac()` to keep computer processing time manageable. All school IDs in the data are real, so we can use that information to link the data with other sources. Specifically, we’re also going to pull in some data on student enrollment in free and reduced lunch from the National Center for Education Statistics and some ethnicity data from the Oregon Department of Education.
@@ -105,13 +108,13 @@ frl <- left_join(frl, stu_counts)
dat <- left_join(dat, frl)
```
-After loading in our three datasets, we’ll join them together to make one cohesive data set to use for modelling. After joining, the data contains both student-level variables (e.g. gender, ethnicity, enrollment in special education/talented and gifted programs, etc.) and district-level variables (e.g. school longitude and latitude, proportion of students who qualify for free and reduced-price lunch, etc.), all of which will be included for each 3 of our `{tidymodels}` tree-based examples.
+After loading in our three datasets, we’ll join them together to make one cohesive data set to use for modelling. After joining, the data contains both student-level variables (e.g. gender, ethnicity, enrollment in special education/talented and gifted programs, etc.) and district-level variables (e.g. school longitude and latitude, proportion of students who qualify for free and reduced-price lunch, etc.), all of which will be included for each 3 of our tidymodels tree-based examples.
For a more complete description of the variables, you can download the data dictionary [here](data_dictionary.csv).
-# Explore the data
+## Explore the data
-We’ll use the `skim()` function from `{skimr}` to take a closer look at our variables. Many numeric predictors are clearly non-normal (see histograms below), but this is no problem as tree-based methods are robust to non-normality.
+We’ll use the `skimr::skim()` to take a closer look at our variables. Many numeric predictors are clearly non-normal (see histograms below), but this is no problem as tree-based methods are robust to non-normality.
```{r}
dat %>%
@@ -122,7 +125,7 @@ dat %>%
select(-starts_with("numeric.p")) # remove quartiles
```
-While most of our predictors are categorical, we can use `{corrplot}` to better visualize the relationships among the numeric variables.
+While most of our predictors are categorical, we can use corrplot to better visualize the relationships among the numeric variables.
```{r warning=FALSE}
dat %>%
@@ -134,9 +137,9 @@ dat %>%
```
-# Split data and resample
+## Split data and resample
-The first step of our analysis is to split our data into two separate sets: a "training" set and a "testing" set. The training set is used to train a model and, if desired, to adjust (i.e., "tune") the model's hyperparameters before evaluating its final performance on our test data. By allowing us to test a model on a new sample, we assess "out of sample" accuracy (i.e., unseen data-—what all predictive models are interested in) and limit overfitting to the training set. We can do this efficiently with the `initial_split()` function. This comes from the `{rsample}` package, which is part of the `{tidymodels}` package that we already loaded. Defaults put 75% of the data in the training set and 25% in the test set, but this can be adjusted with the `prop` argument. Then, we’ll extract the training data from our split object and assign it a name.
+The first step of our analysis is to split our data into two separate sets: a "training" set and a "testing" set. The training set is used to train a model and, if desired, to adjust (i.e., "tune") the model's hyperparameters before evaluating its final performance on our test data. By allowing us to test a model on a new sample, we assess "out of sample" accuracy (i.e., unseen data-—what all predictive models are interested in) and limit overfitting to the training set. We can do this efficiently with the `initial_split()` function. This comes from the rsample package, which is part of the tidymodels package that we already loaded. Defaults put 75% of the data in the training set and 25% in the test set, but this can be adjusted with the `prop` argument. Then, we’ll extract the training data from our split object and assign it a name.
To further prevent over-fitting, we’ll resample our data using `vfold_cv()`. This function outputs k-*fold* cross-validated versions of our training data, where k = the number of times we resample (unsure why v- is used instead of k- here). By using k = 10 data sets, we get a better estimate of the model's out-of-sample accuracy. On top of decreasing bias from over-fitting, this is essential when tuning hyperparameters (though we plan to apply defaults and not tune here, for brevity). Though our use of 10-fold cross validation is both frequently used and effective, it should be noted that other methods (e.g., bootstrap resampling) or other k-values are sometimes used to accomplish the same goal.
@@ -151,7 +154,7 @@ train <- training(split)
cv <- vfold_cv(train)
```
-# Pre-processing
+## Pre-processing
Before we add in our data to the model, we’re going to set up an object that pre-processes our data. This is called a *recipe*. To create a recipe, you’ll first specify a formula for your model, indicating which variable is your outcome and which are your predictors. Using `~.` here will indicate that we want to use all variables other than `score` as predictors. Then, we can specify a series of pre-processing steps for our data that directs our recipe to assign our variables a role or performs feature engineering steps. Pre-processing may be sound uncommon, but if you've ever used `lm()` (or several other `R` functions) you've done some of this by simply calling the function (e.g., automatic dummy-coding to handle categorical data). This is beneficial because it gives the analyst more control, despite adding complexity to the process.
@@ -170,37 +173,37 @@ rec <- recipe(score ~ ., train) %>%
```
-# Create a model
+## Create a model
-The last step before bringing in our data is to specify our model. This will call upon functions from the `{parsnip}` package, which standardizes language for specifying a multitude of statistical models. There are a few core elements that you will need to specify for each model
+The last step before bringing in our data is to specify our model. This will call upon functions from the parsnip package, which standardizes language for specifying a multitude of statistical models. There are a few core elements that you will need to specify for each model
-## The type of model
+### The type of model
This indicates what type of model you choose to fit, each of which will be a different function. We’ll be focusing on decision tree methods using `bag_tree()`, `random_forest()`, and `boost_tree()`. A full list of models can be found here https://www.tidymodels.org/find/parsnip/
-## The engine
+### The engine
`set_engine()` calls the package to support the model you specified above.
-## The mode
+### The mode
`set_mode()` indicates the type of prediction you’d like to use in your model, you’ll choose between regression and classification. Since we are looking to predict student scores, which is a continuous predictor, we’ll be choosing regression.
-## The arguments
+### The arguments
`set_args()` allows you to set values for various parameters for your model, each model type will have a specific set of parameters that can be altered. For these parameters, you can either set a particular value or you can use the tune function to search for the optimal value of each parameter. Tuning requires a few extra steps, so we will leave the default arguments for clarity. For more information on tuning check out https://tune.tidymodels.org/.
-# Create a workflow
+## Create a workflow
Up to this point we’ve been setting up a lot of individual elements and now it is time to combine them to create a cohesive framework, called a *workflow*, so we can run our desired models. First, we’ll use the `workflow()` command and then we’ll pulling the recipe and model we already created. The next section shows three examples of specifying models and creating a workflow for different decision tree methods.
-# Model Examples
+## Model Examples
-## Bagged trees
+### Bagged trees
A bagged tree approach creates multiple subsets of data from the training set which are randomly chosen with replacement. Each subset of data is used to train a given decision tree. In the end, we have an ensemble of different models. The predictions from all the different trees are averaged together, giving us a stronger prediction than one tree could independently.
-### Specify model
+#### Specify model
```{r}
set.seed(100)
@@ -209,7 +212,7 @@ mod_bag <- bag_tree() %>%
set_engine("rpart", times = 10) # 10 bootstrap resamples
```
-### Create workflow
+#### Create workflow
```{r}
wflow_bag <- workflow() %>%
@@ -217,7 +220,7 @@ wflow_bag <- workflow() %>%
add_model(mod_bag)
```
-### Fit the model
+#### Fit the model
```{r cache=TRUE, message=FALSE}
set.seed(100)
@@ -232,7 +235,7 @@ fit_bag <- fit_resamples(
extract = function(x) extract_model(x)))
```
-### Visualize
+#### Visualize
The plot below shows the root nodes from a bagged tree made of 100 trees (10 folds x 10 bootstrapped resamples). Root nodes are the 1st node in a decision tree, and they are determined by which variable best optimizes a loss function (e.g., minimizes mean square error [MSE] for continuous outcomes or Gini Index for categorical outcomes). Put roughly, the most common root nodes can be thought of as the most "important" predictors.
@@ -259,11 +262,11 @@ bag_roots(fit_bag) %>%
labs(x = "root", y = "count")
```
-## Random forest
+### Random forest
Random forest is similar to bagged tree methodology but goes one step further. In addition to taking random subsets of data, the model also draws a random selection of features. Instead of utilizing all features, the random subset of features allows more predictors to be eligible root nodes. This is particularly useful for handling high dimensionality data (e.g., have more variables than participants/cases).
-### Specify the model
+#### Specify the model
```{r}
set.seed(100)
@@ -276,7 +279,7 @@ mod_rf <-rand_forest() %>%
set_args(trees = 1000)
```
-### Create workflow
+#### Create workflow
```{r}
wflow_rf <- workflow() %>%
@@ -284,7 +287,7 @@ wflow_rf <- workflow() %>%
add_recipe(rec)
```
-### Fit the model
+#### Fit the model
```{r cache=TRUE, message=FALSE}
set.seed(100)
@@ -300,7 +303,7 @@ fit_rf <- fit_resamples(
)
```
-### Visualize
+#### Visualize
The plot below shows the root nodes from a random forest with 1000 trees (specified using `set_args(trees = 1000)` in the parsnip model object).
@@ -338,11 +341,11 @@ rf_roots(fit_rf) %>%
labs(x = "root", y = "count")
```
-## Boosted trees
+### Boosted trees
Boosted trees, like bagged trees, are an ensemble model. Instead of applying successive models to resampled data and pooling estimates, boosted trees fit the next tree to the residuals (i.e., error term) of the prior tree. The goal is to minimize residual error through multiple trees, and is typically done with fairly "shallow" decision tree (i.e., 1-6 splits in each tree). Though each model is only slightly improving the error rate, the sequential use of many shallow trees makes computationally efficient (i.e. reduced run time) and highly accurate predictions.
-### Specify the model
+#### Specify the model
```{r}
mod_boost <- boost_tree() %>%
@@ -350,7 +353,7 @@ mod_boost <- boost_tree() %>%
set_mode("regression")
```
-### Create workflow
+#### Create workflow
```{r}
wflow_boost <- workflow() %>%
@@ -358,7 +361,7 @@ wflow_boost <- workflow() %>%
add_model(mod_boost)
```
-### Fit the model
+#### Fit the model
```{r cache=TRUE, message=FALSE}
set.seed(100)
@@ -373,11 +376,11 @@ fit_boost <- fit_resamples(
)
```
-### Visualize
+#### Visualize
-One of the few downfalls of `{tidymodels}` is its (current) inability to plot these tree-based models. For the past two models, it was simpler to extract root nodes and plot them, but their interpretation (as we're fitting to residuals instead of data sets) are not straightforward. For that reason, we don't have any pretty plots here. Instead, we'll skip to evaluating the metrics of all models.
+One of the few downfalls of tidymodels is its (current) inability to plot these tree-based models. For the past two models, it was simpler to extract root nodes and plot them, but their interpretation (as we're fitting to residuals instead of data sets) are not straightforward. For that reason, we don't have any pretty plots here. Instead, we'll skip to evaluating the metrics of all models.
-# Evaluate metrics
+## Evaluate metrics
After running these three models, it’s time to evaluate their performance. We can do this with `tune::collect_metrics()`. The table below shows the estimate of the out-of-sample performance for each of our 3 models.
@@ -393,7 +396,7 @@ collect_metrics(fit_bag) %>%
Here, we are faced with a common problem in the machine learning world: choosing between models that perform similarly (see overlapping standard errors). Whether we would prefer random forests or bagged trees may depend on computational efficiency (i.e., time) or other factors. In practice, tuning several hyperparameters may have made one model clearly preferable over the others, but in our case - relying on all defaults - we would probably have similar performance with both models on a new data set and would prefer random forest or boosted tree models for their efficiency.
-# Out-of-sample performance
+## Out-of-sample performance
The final step is to apply each trained model to our test data using `last_fit()`.
@@ -430,7 +433,7 @@ collect_metrics(final_fit_bag) %>%
knitr::kable()
```
-After applying our 3 trained models to the unseen test data, it looks like random forest is the winner since it has the lowest RMSE. In this example, we only used 1% of the data to train these models, which could make it difficult to meaningfully compare their performance. However, the random forest model also results in the best out-of-sample prediction (RMSE = 83.47) when using all of the available data, which we did for the [Kaggle competition](https://www.kaggle.com/c/edld-654-spring-2020/leaderboard).
+After applying our 3 trained models to the unseen test data, it looks like the boosted tree model is the winner since it has the lowest RMSE. In this example, we only used 1% of the data to train these models, which could make it difficult to meaningfully compare their performance. In practice, the random forest model results in the best out-of-sample prediction when using all of the available data, which we did for the [Kaggle competition](https://www.kaggle.com/c/edld-654-spring-2020/leaderboard).
Session Info
```{r echo=FALSE}
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.markdown b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.markdown
new file mode 100644
index 0000000..7b01482
--- /dev/null
+++ b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index.markdown
@@ -0,0 +1,690 @@
+---
+title: 'Decision Tree Learning in R'
+layout: single
+author: Brendan Cullen, Cianna Bedford-Petersen & Christopher Loan
+date: '2020-06-02'
+slug: []
+categories: []
+tags: []
+subtitle: ''
+summary: 'An overview and worked example of tree-based machine learning methods in R using tidymodels'
+authors: []
+lastmod: ''
+featured: no
+image:
+ caption: 'Image by Ilona Ilyés from Pixabay'
+ focal_point: ''
+ preview_only: FALSE
+projects: []
+---
+
+
+
+
+
+
+RStudio has recently released a cohesive suite of packages for modelling and machine learning, called tidymodels. The successor to Max Kuhn’s caret package, tidymodels allows for a tidy approach to your data from start to finish. We’re going to walk through the basics for getting off the ground with tidymodels and demonstrate its application to three different tree-based methods for predicting student test scores. For further information about the package, you can visit https://www.tidymodels.org/.
+
+## Setup
+
+
+
+
+Load both the tidyverse and tidymodels packages into your environment. We’ll also load in the skimr package to help us with some descriptives for our data and a host of other packages that will be required to run our machine learning models.
+
+
+```r
+library(tidymodels)
+library(tidyverse) # manipulating data
+library(skimr) # data visualization
+library(baguette) # bagged trees
+library(future) # parallel processing & decrease computation time
+library(xgboost) # boosted trees
+```
+
+## Import the data
+
+We use simulated data which approximates reading and math scores for ~189,000 3rd-8th grade students in Oregon public schools see [this Kaggle page](https://www.kaggle.com/c/edld-654-spring-2020) for details. For the purpose of demonstration, we’ll be sampling 1% of the data with `sample_frac()` to keep computer processing time manageable. All school IDs in the data are real, so we can use that information to link the data with other sources. Specifically, we’re also going to pull in some data on student enrollment in free and reduced lunch from the National Center for Education Statistics and some ethnicity data from the Oregon Department of Education.
+
+
+```r
+set.seed(100)
+
+# import data and perform initial cleaning
+# initial cleaning steps include:
+# *recode NA's for lang_cd and ayp_lep to more meaningful values
+# *remove vars with entirely missing data
+# Note: the data is called 'train.csv', but we will actually further split this into its own training and testing data
+
+dat <- read_csv(here::here("static", "data", "train.csv")) %>%
+ select(-classification) %>% # remove this variable because it's redundant with `score`
+ mutate(lang_cd = ifelse(is.na(lang_cd), "E", lang_cd),
+ ayp_lep = ifelse(is.na(ayp_lep), "G", ayp_lep)) %>%
+ sample_frac(.01) %>% # sample 1% of the data to reduce run time
+ janitor::remove_empty(c("rows", "cols")) %>%
+ drop_na() %>%
+ select_if(~length(unique(.x)) > 1)
+
+# import fall membership report ethcnicity data and do some basic cleaning and renaming
+sheets <- readxl::excel_sheets(here::here("static", "data", "fallmembershipreport_20192020.xlsx"))
+
+ode_schools <- readxl::read_xlsx(here::here("static", "data", "fallmembershipreport_20192020.xlsx"),
+ sheet = sheets[4])
+
+ethnicities <- ode_schools %>%
+ select(attnd_schl_inst_id = `Attending School ID`,
+ attnd_dist_inst_id = `Attending District Institution ID`,
+ sch_name = `School Name`,
+ contains("%")) %>%
+ janitor::clean_names()
+
+names(ethnicities) <- gsub("x2019_20_percent", "p", names(ethnicities))
+
+# join ethnicity data with original dataset
+dat <- left_join(dat, ethnicities)
+
+# import and tidy free and reduced lunch data
+frl <- rio::import("https://nces.ed.gov/ccd/Data/zip/ccd_sch_033_1718_l_1a_083118.zip",
+ setclass = "tbl_df") %>%
+ janitor::clean_names() %>%
+ filter(st == "OR") %>%
+ select(ncessch, lunch_program, student_count) %>%
+ mutate(student_count = replace_na(student_count, 0)) %>%
+ pivot_wider(names_from = lunch_program,
+ values_from = student_count) %>%
+ janitor::clean_names() %>%
+ mutate(ncessch = as.double(ncessch))
+
+# import student counts for each school across grades
+stu_counts <- rio::import("https://github.com/datalorax/ach-gap-variability/raw/master/data/achievement-gaps-geocoded.csv", setclass = "tbl_df") %>%
+ filter(state == "OR" & year == 1718) %>%
+ count(ncessch, wt = n) %>%
+ mutate(ncessch = as.double(ncessch))
+
+# join frl and stu_counts data
+frl <- left_join(frl, stu_counts)
+
+# add frl data to train data
+dat <- left_join(dat, frl)
+```
+
+After loading in our three datasets, we’ll join them together to make one cohesive data set to use for modelling. After joining, the data contains both student-level variables (e.g. gender, ethnicity, enrollment in special education/talented and gifted programs, etc.) and district-level variables (e.g. school longitude and latitude, proportion of students who qualify for free and reduced-price lunch, etc.), all of which will be included for each 3 of our tidymodels tree-based examples.
+
+For a more complete description of the variables, you can download the data dictionary [here](data_dictionary.csv).
+
+## Explore the data
+
+We’ll use the `skimr::skim()` to take a closer look at our variables. Many numeric predictors are clearly non-normal (see histograms below), but this is no problem as tree-based methods are robust to non-normality.
+
+
+```r
+dat %>%
+ select(-contains("id"), -ncessch, -missing, -not_applicable) %>% # remove ID and irrelevant variables
+ mutate(tst_dt = lubridate::as_date(lubridate::mdy_hms(tst_dt))) %>% # covert test date to date
+ modify_if(is.character, as.factor) %>% # convert character vars to factors
+ skim() %>%
+ select(-starts_with("numeric.p")) # remove quartiles
+```
+
+
+Table: Table 1: Data summary
+
+| | |
+|:------------------------|:----------|
+|Name |Piped data |
+|Number of rows |1864 |
+|Number of columns |41 |
+|_______________________ | |
+|Column type frequency: | |
+|Date |1 |
+|factor |25 |
+|numeric |15 |
+|________________________ | |
+|Group variables |None |
+
+
+**Variable type: Date**
+
+|skim_variable | n_missing| complete_rate|min |max |median | n_unique|
+|:-------------|---------:|-------------:|:----------|:----------|:----------|--------:|
+|tst_dt | 0| 1|2018-03-19 |2018-06-08 |2018-05-18 | 47|
+
+
+**Variable type: factor**
+
+|skim_variable | n_missing| complete_rate|ordered | n_unique|top_counts |
+|:-------------------|---------:|-------------:|:-------|--------:|:----------------------------------|
+|gndr | 0| 1|FALSE | 2|M: 958, F: 906 |
+|ethnic_cd | 0| 1|FALSE | 7|W: 1153, H: 455, M: 91, A: 84 |
+|tst_bnch | 0| 1|FALSE | 6|G4: 337, 2B: 334, G7: 316, G6: 308 |
+|migrant_ed_fg | 0| 1|FALSE | 2|N: 1805, Y: 59 |
+|ind_ed_fg | 0| 1|FALSE | 2|N: 1841, Y: 23 |
+|sp_ed_fg | 0| 1|FALSE | 2|N: 1612, Y: 252 |
+|tag_ed_fg | 0| 1|FALSE | 2|N: 1755, Y: 109 |
+|econ_dsvntg | 0| 1|FALSE | 2|Y: 1077, N: 787 |
+|ayp_lep | 0| 1|FALSE | 10|G: 1481, F: 155, Y: 84, E: 62 |
+|stay_in_dist | 0| 1|FALSE | 2|Y: 1822, N: 42 |
+|stay_in_schl | 0| 1|FALSE | 2|Y: 1806, N: 58 |
+|dist_sped | 0| 1|FALSE | 2|N: 1849, Y: 15 |
+|trgt_assist_fg | 0| 1|FALSE | 2|N: 1786, Y: 78 |
+|ayp_schl_partic | 0| 1|FALSE | 2|Y: 1849, N: 15 |
+|ayp_dist_prfrm | 0| 1|FALSE | 2|Y: 1812, N: 52 |
+|ayp_schl_prfrm | 0| 1|FALSE | 2|Y: 1781, N: 83 |
+|rc_schl_partic | 0| 1|FALSE | 2|Y: 1849, N: 15 |
+|rc_dist_prfrm | 0| 1|FALSE | 2|Y: 1812, N: 52 |
+|rc_schl_prfrm | 0| 1|FALSE | 2|Y: 1781, N: 83 |
+|lang_cd | 0| 1|FALSE | 2|E: 1816, S: 48 |
+|tst_atmpt_fg | 0| 1|FALSE | 2|Y: 1861, P: 3 |
+|grp_rpt_schl_partic | 0| 1|FALSE | 2|Y: 1849, N: 15 |
+|grp_rpt_dist_prfrm | 0| 1|FALSE | 2|Y: 1853, N: 11 |
+|grp_rpt_schl_prfrm | 0| 1|FALSE | 2|Y: 1838, N: 26 |
+|sch_name | 1| 1|FALSE | 681|Sto: 13, Whi: 11, Hig: 10, J W: 10 |
+
+
+**Variable type: numeric**
+
+|skim_variable | n_missing| complete_rate| mean| sd|hist |
+|:----------------------------------|---------:|-------------:|-------:|------:|:-----|
+|enrl_grd | 0| 1| 5.47| 1.67|▇▅▃▅▃ |
+|score | 0| 1| 2497.11| 115.24|▁▃▇▂▁ |
+|lat | 0| 1| 44.73| 1.05|▂▁▃▅▇ |
+|lon | 0| 1| -122.54| 1.17|▆▇▁▁▁ |
+|p_american_indian_alaska_native | 1| 1| 0.01| 0.05|▇▁▁▁▁ |
+|p_asian | 1| 1| 0.04| 0.07|▇▁▁▁▁ |
+|p_native_hawaiian_pacific_islander | 1| 1| 0.01| 0.01|▇▁▁▁▁ |
+|p_black_african_american | 1| 1| 0.02| 0.04|▇▁▁▁▁ |
+|p_hispanic_latino | 1| 1| 0.24| 0.19|▇▅▂▁▁ |
+|p_white | 1| 1| 0.61| 0.20|▁▃▅▇▆ |
+|p_multiracial | 1| 1| 0.07| 0.03|▇▆▁▁▁ |
+|free_lunch_qualified | 0| 1| 224.52| 134.82|▇▇▃▁▁ |
+|reduced_price_lunch_qualified | 0| 1| 39.10| 23.64|▆▇▃▁▁ |
+|no_category_codes | 0| 1| 263.63| 151.80|▆▇▃▁▁ |
+|n | 0| 1| 793.78| 532.54|▇▃▂▁▁ |
+
+While most of our predictors are categorical, we can use corrplot to better visualize the relationships among the numeric variables.
+
+
+```r
+dat %>%
+ select(-contains("id"), -ncessch, -missing, -not_applicable) %>%
+ select_if(is.numeric) %>%
+ select(score, everything()) %>%
+ cor(use = "complete.obs") %>%
+ corrplot::corrplot()
+```
+
+
+
+
+## Split data and resample
+
+The first step of our analysis is to split our data into two separate sets: a "training" set and a "testing" set. The training set is used to train a model and, if desired, to adjust (i.e., "tune") the model's hyperparameters before evaluating its final performance on our test data. By allowing us to test a model on a new sample, we assess "out of sample" accuracy (i.e., unseen data-—what all predictive models are interested in) and limit overfitting to the training set. We can do this efficiently with the `initial_split()` function. This comes from the rsample package, which is part of the tidymodels package that we already loaded. Defaults put 75% of the data in the training set and 25% in the test set, but this can be adjusted with the `prop` argument. Then, we’ll extract the training data from our split object and assign it a name.
+
+To further prevent over-fitting, we’ll resample our data using `vfold_cv()`. This function outputs k-*fold* cross-validated versions of our training data, where k = the number of times we resample (unsure why v- is used instead of k- here). By using k = 10 data sets, we get a better estimate of the model's out-of-sample accuracy. On top of decreasing bias from over-fitting, this is essential when tuning hyperparameters (though we plan to apply defaults and not tune here, for brevity). Though our use of 10-fold cross validation is both frequently used and effective, it should be noted that other methods (e.g., bootstrap resampling) or other k-values are sometimes used to accomplish the same goal.
+
+
+```r
+# split the data
+split <- initial_split(dat)
+
+# extract the training data
+train <- training(split)
+
+# resample the data with 10-fold cross-validation (10-fold by default)
+cv <- vfold_cv(train)
+```
+
+## Pre-processing
+
+Before we add in our data to the model, we’re going to set up an object that pre-processes our data. This is called a *recipe*. To create a recipe, you’ll first specify a formula for your model, indicating which variable is your outcome and which are your predictors. Using `~.` here will indicate that we want to use all variables other than `score` as predictors. Then, we can specify a series of pre-processing steps for our data that directs our recipe to assign our variables a role or performs feature engineering steps. Pre-processing may be sound uncommon, but if you've ever used `lm()` (or several other `R` functions) you've done some of this by simply calling the function (e.g., automatic dummy-coding to handle categorical data). This is beneficial because it gives the analyst more control, despite adding complexity to the process.
+
+A complete list of possible pre-processing steps can be found here: https://www.tidymodels.org/find/recipes/
+
+
+
+```r
+rec <- recipe(score ~ ., train) %>%
+ step_mutate(tst_dt = as.numeric(lubridate::mdy_hms(tst_dt))) %>% # convert `test date` variable to a date
+ update_role(contains("id"), ncessch, new_role = "id vars") %>% # declare ID variables
+ step_nzv(all_predictors(), freq_cut = 0, unique_cut = 0) %>% # remove variables with zero variances
+ step_novel(all_nominal()) %>% # prepares test data to handle previously unseen factor levels
+ step_unknown(all_nominal()) %>% # categorizes missing categorical data (NA's) as `unknown`
+ step_medianimpute(all_numeric(), -all_outcomes(), -has_role("id vars")) %>% # replaces missing numeric observations with the median
+ step_dummy(all_nominal(), -has_role("id vars")) # dummy codes categorical variables
+```
+
+
+## Create a model
+
+The last step before bringing in our data is to specify our model. This will call upon functions from the parsnip package, which standardizes language for specifying a multitude of statistical models. There are a few core elements that you will need to specify for each model
+
+### The type of model
+
+This indicates what type of model you choose to fit, each of which will be a different function. We’ll be focusing on decision tree methods using `bag_tree()`, `random_forest()`, and `boost_tree()`. A full list of models can be found here https://www.tidymodels.org/find/parsnip/
+
+### The engine
+
+`set_engine()` calls the package to support the model you specified above.
+
+### The mode
+
+`set_mode()` indicates the type of prediction you’d like to use in your model, you’ll choose between regression and classification. Since we are looking to predict student scores, which is a continuous predictor, we’ll be choosing regression.
+
+### The arguments
+
+`set_args()` allows you to set values for various parameters for your model, each model type will have a specific set of parameters that can be altered. For these parameters, you can either set a particular value or you can use the tune function to search for the optimal value of each parameter. Tuning requires a few extra steps, so we will leave the default arguments for clarity. For more information on tuning check out https://tune.tidymodels.org/.
+
+## Create a workflow
+
+Up to this point we’ve been setting up a lot of individual elements and now it is time to combine them to create a cohesive framework, called a *workflow*, so we can run our desired models. First, we’ll use the `workflow()` command and then we’ll pulling the recipe and model we already created. The next section shows three examples of specifying models and creating a workflow for different decision tree methods.
+
+## Model Examples
+
+### Bagged trees
+
+A bagged tree approach creates multiple subsets of data from the training set which are randomly chosen with replacement. Each subset of data is used to train a given decision tree. In the end, we have an ensemble of different models. The predictions from all the different trees are averaged together, giving us a stronger prediction than one tree could independently.
+
+#### Specify model
+
+
+```r
+set.seed(100)
+mod_bag <- bag_tree() %>%
+ set_mode("regression") %>%
+ set_engine("rpart", times = 10) # 10 bootstrap resamples
+```
+
+#### Create workflow
+
+
+```r
+wflow_bag <- workflow() %>%
+ add_recipe(rec) %>%
+ add_model(mod_bag)
+```
+
+#### Fit the model
+
+
+```r
+set.seed(100)
+plan(multisession)
+
+fit_bag <- fit_resamples(
+ wflow_bag,
+ cv,
+ metrics = metric_set(rmse, rsq),
+ control = control_resamples(verbose = TRUE,
+ save_pred = TRUE,
+ extract = function(x) extract_model(x)))
+```
+
+#### Visualize
+
+The plot below shows the root nodes from a bagged tree made of 100 trees (10 folds x 10 bootstrapped resamples). Root nodes are the 1st node in a decision tree, and they are determined by which variable best optimizes a loss function (e.g., minimizes mean square error [MSE] for continuous outcomes or Gini Index for categorical outcomes). Put roughly, the most common root nodes can be thought of as the most "important" predictors.
+
+
+```r
+# extract roots
+bag_roots <- function(x){
+ x %>%
+ select(.extracts) %>%
+ unnest(cols = c(.extracts)) %>%
+ mutate(models = map(.extracts,
+ ~.x$model_df)) %>%
+ select(-.extracts) %>%
+ unnest(cols = c(models)) %>%
+ mutate(root = map_chr(model,
+ ~as.character(.x$fit$frame[1, 1]))) %>%
+ select(root)
+}
+
+# plot
+bag_roots(fit_bag) %>%
+ ggplot(mapping = aes(x = fct_rev(fct_infreq(root)))) +
+ geom_bar() +
+ coord_flip() +
+ labs(x = "root", y = "count")
+```
+
+
+
+### Random forest
+
+Random forest is similar to bagged tree methodology but goes one step further. In addition to taking random subsets of data, the model also draws a random selection of features. Instead of utilizing all features, the random subset of features allows more predictors to be eligible root nodes. This is particularly useful for handling high dimensionality data (e.g., have more variables than participants/cases).
+
+#### Specify the model
+
+
+```r
+set.seed(100)
+mod_rf <-rand_forest() %>%
+ set_engine("ranger",
+ num.threads = parallel::detectCores(),
+ importance = "permutation",
+ verbose = TRUE) %>%
+ set_mode("regression") %>%
+ set_args(trees = 1000)
+```
+
+#### Create workflow
+
+
+```r
+wflow_rf <- workflow() %>%
+ add_model(mod_rf) %>%
+ add_recipe(rec)
+```
+
+#### Fit the model
+
+
+```r
+set.seed(100)
+plan(multisession)
+
+fit_rf <- fit_resamples(
+ wflow_rf,
+ cv,
+ metrics = metric_set(rmse, rsq),
+ control = control_resamples(verbose = TRUE,
+ save_pred = TRUE,
+ extract = function(x) x)
+)
+```
+
+#### Visualize
+
+The plot below shows the root nodes from a random forest with 1000 trees (specified using `set_args(trees = 1000)` in the parsnip model object).
+
+
+```r
+# extract roots
+rf_tree_roots <- function(x){
+ map_chr(1:1000,
+ ~ranger::treeInfo(x, tree = .)[1, "splitvarName"])
+}
+
+rf_roots <- function(x){
+ x %>%
+ select(.extracts) %>%
+ unnest(cols = c(.extracts)) %>%
+ mutate(fit = map(.extracts,
+ ~.x$fit$fit$fit),
+ oob_rmse = map_dbl(fit,
+ ~sqrt(.x$prediction.error)),
+ roots = map(fit,
+ ~rf_tree_roots(.))
+ ) %>%
+ select(roots) %>%
+ unnest(cols = c(roots))
+}
+
+# plot
+rf_roots(fit_rf) %>%
+ group_by(roots) %>%
+ count() %>%
+ arrange(desc(n)) %>%
+ filter(n > 75) %>%
+ ggplot(aes(fct_reorder(roots, n), n)) +
+ geom_col() +
+ coord_flip() +
+ labs(x = "root", y = "count")
+```
+
+
+
+### Boosted trees
+
+Boosted trees, like bagged trees, are an ensemble model. Instead of applying successive models to resampled data and pooling estimates, boosted trees fit the next tree to the residuals (i.e., error term) of the prior tree. The goal is to minimize residual error through multiple trees, and is typically done with fairly "shallow" decision tree (i.e., 1-6 splits in each tree). Though each model is only slightly improving the error rate, the sequential use of many shallow trees makes computationally efficient (i.e. reduced run time) and highly accurate predictions.
+
+#### Specify the model
+
+
+```r
+mod_boost <- boost_tree() %>%
+ set_engine("xgboost", nthreads = parallel::detectCores()) %>%
+ set_mode("regression")
+```
+
+#### Create workflow
+
+
+```r
+wflow_boost <- workflow() %>%
+ add_recipe(rec) %>%
+ add_model(mod_boost)
+```
+
+#### Fit the model
+
+
+```r
+set.seed(100)
+plan(multisession)
+
+fit_boost <- fit_resamples(
+ wflow_boost,
+ cv,
+ metrics = metric_set(rmse, rsq),
+ control = control_resamples(verbose = TRUE,
+ save_pred = TRUE)
+)
+```
+
+#### Visualize
+
+One of the few downfalls of tidymodels is its (current) inability to plot these tree-based models. For the past two models, it was simpler to extract root nodes and plot them, but their interpretation (as we're fitting to residuals instead of data sets) are not straightforward. For that reason, we don't have any pretty plots here. Instead, we'll skip to evaluating the metrics of all models.
+
+## Evaluate metrics
+
+After running these three models, it’s time to evaluate their performance. We can do this with `tune::collect_metrics()`. The table below shows the estimate of the out-of-sample performance for each of our 3 models.
+
+
+```r
+collect_metrics(fit_bag) %>%
+ bind_rows(collect_metrics(fit_rf)) %>%
+ bind_rows(collect_metrics(fit_boost)) %>%
+ filter(.metric == "rmse") %>%
+ mutate(model = c("bag", "rf", "boost")) %>%
+ select(model, everything()) %>%
+ knitr::kable()
+```
+
+
+
+|model |.metric |.estimator | mean| n| std_err|
+|:-----|:-------|:----------|--------:|--:|--------:|
+|bag |rmse |standard | 96.70756| 10| 1.356172|
+|rf |rmse |standard | 93.66723| 10| 1.475393|
+|boost |rmse |standard | 92.46805| 10| 1.478565|
+
+Here, we are faced with a common problem in the machine learning world: choosing between models that perform similarly (see overlapping standard errors). Whether we would prefer random forests or bagged trees may depend on computational efficiency (i.e., time) or other factors. In practice, tuning several hyperparameters may have made one model clearly preferable over the others, but in our case - relying on all defaults - we would probably have similar performance with both models on a new data set and would prefer random forest or boosted tree models for their efficiency.
+
+## Out-of-sample performance
+
+The final step is to apply each trained model to our test data using `last_fit()`.
+
+
+```r
+# bagged trees
+final_fit_bag <- last_fit(
+ wflow_bag,
+ split = split
+)
+
+# random forest
+final_fit_rf <- last_fit(
+ wflow_rf,
+ split = split
+)
+
+# boosted trees
+final_fit_boost <- last_fit(
+ wflow_boost,
+ split = split
+)
+```
+
+The table below shows the actual out-of-sample performance for each of our 3 models.
+
+
+```r
+# show performance on test data
+collect_metrics(final_fit_bag) %>%
+ bind_rows(collect_metrics(final_fit_rf)) %>%
+ bind_rows(collect_metrics(final_fit_boost)) %>%
+ filter(.metric == "rmse") %>%
+ mutate(model = c("bag", "rf", "boost")) %>%
+ select(model, everything()) %>%
+ knitr::kable()
+```
+
+
+
+|model |.metric |.estimator | .estimate|
+|:-----|:-------|:----------|---------:|
+|bag |rmse |standard | 96.62098|
+|rf |rmse |standard | 93.80719|
+|boost |rmse |standard | 90.30180|
+
+After applying our 3 trained models to the unseen test data, it looks like the boosted tree model is the winner since it has the lowest RMSE. In this example, we only used 1% of the data to train these models, which could make it difficult to meaningfully compare their performance. In practice, the random forest model results in the best out-of-sample prediction when using all of the available data, which we did for the [Kaggle competition](https://www.kaggle.com/c/edld-654-spring-2020/leaderboard).
+
+Session Info
+
+```
+## ─ Session info ───────────────────────────────────────────────────────────────
+## setting value
+## version R version 4.0.3 (2020-10-10)
+## os macOS Catalina 10.15.7
+## system x86_64, darwin17.0
+## ui X11
+## language (EN)
+## collate en_US.UTF-8
+## ctype en_US.UTF-8
+## tz America/Los_Angeles
+## date 2021-12-01
+##
+## ─ Packages ───────────────────────────────────────────────────────────────────
+## package * version date lib source
+## assertthat 0.2.1 2019-03-21 [1] CRAN (R 4.0.2)
+## backports 1.1.10 2020-09-15 [1] CRAN (R 4.0.2)
+## baguette * 0.1.0 2020-10-28 [1] CRAN (R 4.0.2)
+## base64enc 0.1-3 2015-07-28 [1] CRAN (R 4.0.2)
+## blob 1.2.1 2020-01-20 [1] CRAN (R 4.0.2)
+## blogdown 1.0.1 2021-01-11 [1] Github (rstudio/blogdown@0f7f73f)
+## bookdown 0.21 2020-10-13 [1] CRAN (R 4.0.3)
+## broom * 0.7.1 2020-10-02 [1] CRAN (R 4.0.2)
+## C50 0.1.3.1 2020-05-26 [1] CRAN (R 4.0.2)
+## cellranger 1.1.0 2016-07-27 [1] CRAN (R 4.0.2)
+## class 7.3-17 2020-04-26 [1] CRAN (R 4.0.3)
+## cli 2.2.0 2020-11-20 [1] CRAN (R 4.0.3)
+## codetools 0.2-16 2018-12-24 [1] CRAN (R 4.0.3)
+## colorspace 2.0-0 2020-11-11 [1] CRAN (R 4.0.2)
+## corrplot 0.84 2017-10-16 [1] CRAN (R 4.0.2)
+## crayon 1.3.4 2017-09-16 [1] CRAN (R 4.0.2)
+## Cubist 0.2.3 2020-01-10 [1] CRAN (R 4.0.2)
+## data.table 1.13.6 2020-12-30 [1] CRAN (R 4.0.2)
+## DBI 1.1.0 2019-12-15 [1] CRAN (R 4.0.2)
+## dbplyr 1.4.4 2020-05-27 [1] CRAN (R 4.0.2)
+## dials * 0.0.8 2020-07-08 [1] CRAN (R 4.0.2)
+## DiceDesign 1.8-1 2019-07-31 [1] CRAN (R 4.0.2)
+## digest 0.6.27 2020-10-24 [1] CRAN (R 4.0.2)
+## dplyr * 1.0.3 2021-01-15 [1] CRAN (R 4.0.2)
+## earth 5.3.0 2020-10-11 [1] CRAN (R 4.0.2)
+## ellipsis 0.3.1 2020-05-15 [1] CRAN (R 4.0.2)
+## evaluate 0.14 2019-05-28 [1] CRAN (R 4.0.1)
+## fansi 0.4.2 2021-01-15 [1] CRAN (R 4.0.2)
+## farver 2.0.3 2020-01-16 [1] CRAN (R 4.0.2)
+## forcats * 0.5.0 2020-03-01 [1] CRAN (R 4.0.2)
+## foreach 1.5.0 2020-03-30 [1] CRAN (R 4.0.2)
+## Formula 1.2-4 2020-10-16 [1] CRAN (R 4.0.2)
+## fs 1.5.0 2020-07-31 [1] CRAN (R 4.0.2)
+## furrr 0.1.0 2018-05-16 [1] CRAN (R 4.0.2)
+## future * 1.18.0 2020-07-09 [1] CRAN (R 4.0.2)
+## generics 0.1.0 2020-10-31 [1] CRAN (R 4.0.2)
+## ggplot2 * 3.3.3 2020-12-30 [1] CRAN (R 4.0.2)
+## globals 0.12.5 2019-12-07 [1] CRAN (R 4.0.2)
+## glue 1.4.2 2020-08-27 [1] CRAN (R 4.0.2)
+## gower 0.2.2 2020-06-23 [1] CRAN (R 4.0.2)
+## GPfit 1.0-8 2019-02-08 [1] CRAN (R 4.0.2)
+## gtable 0.3.0 2019-03-25 [1] CRAN (R 4.0.2)
+## hardhat 0.1.4 2020-07-02 [1] CRAN (R 4.0.2)
+## haven 2.3.1 2020-06-01 [1] CRAN (R 4.0.2)
+## highr 0.8 2019-03-20 [1] CRAN (R 4.0.2)
+## hms 0.5.3 2020-01-08 [1] CRAN (R 4.0.2)
+## htmltools 0.5.0 2020-06-16 [1] CRAN (R 4.0.2)
+## httr 1.4.2 2020-07-20 [1] CRAN (R 4.0.2)
+## infer * 0.5.4.9000 2021-01-19 [1] Github (tidymodels/infer@9044fff)
+## inum 1.0-1 2019-04-25 [1] CRAN (R 4.0.2)
+## ipred 0.9-9 2019-04-28 [1] CRAN (R 4.0.2)
+## iterators 1.0.12 2019-07-26 [1] CRAN (R 4.0.2)
+## jsonlite 1.7.2 2020-12-09 [1] CRAN (R 4.0.2)
+## knitr 1.30 2020-09-22 [1] CRAN (R 4.0.2)
+## labeling 0.4.2 2020-10-20 [1] CRAN (R 4.0.2)
+## lattice 0.20-41 2020-04-02 [1] CRAN (R 4.0.3)
+## lava 1.6.7 2020-03-05 [1] CRAN (R 4.0.2)
+## lhs 1.0.2 2020-04-13 [1] CRAN (R 4.0.2)
+## libcoin 1.0-6 2020-08-14 [1] CRAN (R 4.0.2)
+## lifecycle 0.2.0 2020-03-06 [1] CRAN (R 4.0.2)
+## listenv 0.8.0 2019-12-05 [1] CRAN (R 4.0.2)
+## lubridate 1.7.9.2 2020-11-13 [1] CRAN (R 4.0.2)
+## magrittr 2.0.1 2020-11-17 [1] CRAN (R 4.0.3)
+## MASS 7.3-51.6 2020-04-26 [1] CRAN (R 4.0.2)
+## Matrix 1.2-18 2019-11-27 [1] CRAN (R 4.0.3)
+## modeldata * 0.0.2 2020-06-22 [1] CRAN (R 4.0.2)
+## modelr 0.1.8 2020-05-19 [1] CRAN (R 4.0.2)
+## munsell 0.5.0 2018-06-12 [1] CRAN (R 4.0.2)
+## mvtnorm 1.1-1 2020-06-09 [1] CRAN (R 4.0.2)
+## nnet 7.3-14 2020-04-26 [1] CRAN (R 4.0.3)
+## parsnip * 0.1.4 2020-10-27 [1] CRAN (R 4.0.2)
+## partykit 1.2-10 2020-10-12 [1] CRAN (R 4.0.2)
+## pillar 1.4.7 2020-11-20 [1] CRAN (R 4.0.2)
+## pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.0.2)
+## plotmo 3.6.0 2020-09-13 [1] CRAN (R 4.0.2)
+## plotrix 3.7-8 2020-04-16 [1] CRAN (R 4.0.2)
+## plyr 1.8.6 2020-03-03 [1] CRAN (R 4.0.2)
+## pROC 1.16.2 2020-03-19 [1] CRAN (R 4.0.2)
+## prodlim 2019.11.13 2019-11-17 [1] CRAN (R 4.0.2)
+## purrr * 0.3.4 2020-04-17 [1] CRAN (R 4.0.2)
+## R6 2.5.0 2020-10-28 [1] CRAN (R 4.0.2)
+## ranger 0.12.1 2020-01-10 [1] CRAN (R 4.0.2)
+## Rcpp 1.0.5 2020-07-06 [1] CRAN (R 4.0.2)
+## readr * 1.4.0 2020-10-05 [1] CRAN (R 4.0.2)
+## readxl 1.3.1 2019-03-13 [1] CRAN (R 4.0.2)
+## recipes * 0.1.14 2020-10-17 [1] CRAN (R 4.0.2)
+## repr 1.1.0 2020-01-28 [1] CRAN (R 4.0.2)
+## reprex 0.3.0 2019-05-16 [1] CRAN (R 4.0.2)
+## reshape2 1.4.4 2020-04-09 [1] CRAN (R 4.0.2)
+## rlang 0.4.10 2020-12-30 [1] CRAN (R 4.0.2)
+## rmarkdown 2.6 2020-12-14 [1] CRAN (R 4.0.2)
+## rpart 4.1-15 2019-04-12 [1] CRAN (R 4.0.3)
+## rsample * 0.0.8 2020-09-23 [1] CRAN (R 4.0.2)
+## rstudioapi 0.13 2020-11-12 [1] CRAN (R 4.0.2)
+## rvest 0.3.6 2020-07-25 [1] CRAN (R 4.0.2)
+## scales * 1.1.1 2020-05-11 [1] CRAN (R 4.0.2)
+## sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 4.0.2)
+## skimr * 2.1.2 2020-07-06 [1] CRAN (R 4.0.2)
+## stringi 1.5.3 2020-09-09 [1] CRAN (R 4.0.2)
+## stringr * 1.4.0 2019-02-10 [1] CRAN (R 4.0.2)
+## survival 3.1-12 2020-04-10 [1] CRAN (R 4.0.0)
+## TeachingDemos 2.12 2020-04-07 [1] CRAN (R 4.0.2)
+## tibble * 3.0.5 2021-01-15 [1] CRAN (R 4.0.2)
+## tidymodels * 0.1.1 2020-07-14 [1] CRAN (R 4.0.2)
+## tidyr * 1.1.2 2020-08-27 [1] CRAN (R 4.0.2)
+## tidyselect 1.1.0 2020-05-11 [1] CRAN (R 4.0.2)
+## tidyverse * 1.3.0 2019-11-21 [1] CRAN (R 4.0.2)
+## timeDate 3043.102 2018-02-21 [1] CRAN (R 4.0.2)
+## tune * 0.1.1 2020-07-08 [1] CRAN (R 4.0.2)
+## vctrs 0.3.6 2020-12-17 [1] CRAN (R 4.0.2)
+## withr 2.4.0 2021-01-16 [1] CRAN (R 4.0.2)
+## workflows * 0.1.2 2020-07-07 [1] CRAN (R 4.0.2)
+## xfun 0.20 2021-01-06 [1] CRAN (R 4.0.3)
+## xgboost * 1.2.0.1 2020-09-02 [1] CRAN (R 4.0.2)
+## xml2 1.3.2 2020-04-23 [1] CRAN (R 4.0.2)
+## yaml 2.2.1 2020-02-01 [1] CRAN (R 4.0.2)
+## yardstick * 0.0.7 2020-07-13 [1] CRAN (R 4.0.2)
+##
+## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
+```
+
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/__packages b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/__packages
new file mode 100644
index 0000000..486b910
--- /dev/null
+++ b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/__packages
@@ -0,0 +1,26 @@
+base
+tidymodels
+broom
+scales
+dials
+dplyr
+ggplot2
+infer
+modeldata
+parsnip
+purrr
+recipes
+rsample
+tibble
+tidyr
+tune
+workflows
+yardstick
+tidyverse
+readr
+stringr
+forcats
+skimr
+baguette
+future
+xgboost
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.RData b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.RData
new file mode 100644
index 0000000..4bea611
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.RData differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdb b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdb
new file mode 100644
index 0000000..1d23617
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdb differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdx b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdx
new file mode 100644
index 0000000..80c3d50
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-10_2bb3b3f01add4c8318d5afa34b8637b2.rdx differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.RData b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.RData
new file mode 100644
index 0000000..664076c
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.RData differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdb b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdb
new file mode 100644
index 0000000..02678f0
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdb differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdx b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdx
new file mode 100644
index 0000000..6ba43f4
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-14_fc506d1990d4a9f8f61a6f838e2ab119.rdx differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.RData b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.RData
new file mode 100644
index 0000000..a331a60
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.RData differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdb b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdb
new file mode 100644
index 0000000..48a2a41
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdb differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdx b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdx
new file mode 100644
index 0000000..abc5120
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-18_4571ab498c9f06dfcb5aa518faf36ef6.rdx differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.RData b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.RData
new file mode 100644
index 0000000..0f4b876
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.RData differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdb b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdb
new file mode 100644
index 0000000..64f7da7
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdb differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdx b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdx
new file mode 100644
index 0000000..8e5de65
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-20_f098ad1f34303e5771e95828695dc318.rdx differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.RData b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.RData
new file mode 100644
index 0000000..fb3c3e5
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.RData differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdb b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdb
new file mode 100644
index 0000000..9422722
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdb differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdx b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdx
new file mode 100644
index 0000000..1ca5162
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_cache/html/unnamed-chunk-3_6ad0f2ee7684e1fa34817a3b499b507e.rdx differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-11-1.png b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-11-1.png
new file mode 100644
index 0000000..f699b30
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-11-1.png differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-15-1.png b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-15-1.png
new file mode 100644
index 0000000..f97fbc7
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-15-1.png differ
diff --git a/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-5-1.png b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-5-1.png
new file mode 100644
index 0000000..9e24d7f
Binary files /dev/null and b/content/blog/2020-06-02-tidymodels-decision-tree-learning-in-r/index_files/figure-html/unnamed-chunk-5-1.png differ
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/certificate.png b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/certificate.png
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/certificate.png
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/certificate.png
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise-operations.png b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise-operations.png
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise-operations.png
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise-operations.png
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_concept_map.png b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_concept_map.png
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_concept_map.png
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_concept_map.png
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_formative_assessment.gif b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_formative_assessment.gif
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_formative_assessment.gif
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/columnwise_formative_assessment.gif
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/featured.jpg b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/featured.jpg
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/featured.jpg
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/featured.jpg
diff --git a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmd b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmarkdown
similarity index 58%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmd
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmarkdown
index 7fff80c..93a7bb2 100644
--- a/content/post/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmd
+++ b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.Rmarkdown
@@ -1,5 +1,6 @@
---
title: Reflections on RStudio Instructor Training
+layout: single
author: Brendan Cullen
date: '2020-09-03'
slug: []
@@ -8,22 +9,23 @@ tags:
- data science
- education
- R
-subtitle: 'tl;dr You should definitely look into it.'
+subtitle: ''
summary: "The 'what' and 'why' of RStudio Instructor Training and resources for those interested in pursuing it."
authors: []
-lastmod: '2020-09-03T21:28:31-07:00'
+lastmod: ''
featured: no
image:
caption: 'Photo by oatawa on iStock'
focal_point: ''
preview_only: no
projects: []
-output:
- blogdown::html_page:
- toc: TRUE
- toc_depth: 4
---
+
+
+
+
+
A while back I wrote about how we [need more data science training](https://bcullen.rbind.io/post/2020-03-08-data-science-training-needs-in-grad-school/) as grad students in psychology and that one of the best ways for us to get this training is to [learn from each other](https://twitter.com/_bcullen/status/1237414725081653249). This is just one of many reasons why I'm so humbled and excited to have recently become an [RStudio Certified Instructor](https://education.rstudio.com/trainers/people/cullen+brendan/) in the tidyverse.
I'm looking forward to start implementing and sharing what I learned with my fellow grad students, especially at the end of this month when I will be leading an introductory R workshop for the new cohort of first year PhD and master's students in my department.
@@ -32,15 +34,15 @@ As a small way of paying it forward, I wanted to offer a reflection on what I th
------------------------------------------------------------------------
-# The *what*
+## The *what*
-::: {.book}
- The best place the start is to read about the RStudio Instructor Training and Certification Program [here](https://education.rstudio.com/trainers/#info). The [RStudio Education Blog](https://education.rstudio.com/categories/certify/) also has lots of helpful posts about the program.
-:::
+
+The best place the start is to read about the RStudio Instructor Training and Certification Program here. The RStudio Education Blog also has lots of helpful posts about the program.
+
The process boils down to three steps.
-## Training Course `r fontawesome::fa("chalkboard-teacher")`
+### Training Course `r fontawesome::fa("chalkboard-teacher")`
The first step is to sign up for the training course, which will likely be held over Zoom and chunked into 3-4 hour segments across 2-3 days. You can access the training materials [here](https://drive.google.com/drive/folders/13ohFt3D0EJ5PDbMaWTxnHH-hwA7G0IvY).
@@ -48,7 +50,7 @@ The training course is an interactive introduction to applying evidence-based te
-## Technical Exam `r fontawesome::fa("laptop-code")`
+### Technical Exam `r fontawesome::fa("laptop-code")`
The technical exam assesses your proficiency in whatever topic for which you are attempting to become a certified instructor. Currently there are options to become a certified instructor in [tidyverse](https://www.tidyverse.org/) and [shiny](https://shiny.rstudio.com/), and each has its own accompanying technical exam.
@@ -56,39 +58,31 @@ I took the tidyverse exam, which, broadly speaking, consists of a series of live
As many others have suggested, a great way to prepare for this exam is to work through the exercises [R for Data Science](https://r4ds.had.co.nz/), particularly for topics that feel rusty to you, and review the community-contributed [solutions](https://jrnold.github.io/r4ds-exercise-solutions/).
-::: {.note}
+
I highly recommend going through these sample exams from the RStudio Education Blog start to finish to get a sense of what you might need to review.
- [Sample Tidyverse Exam 1](https://education.rstudio.com/blog/2020/02/instructor-certification-exams/#tidyverse-certification-exam) \| [solutions](https://marlycormar.github.io/tidyverse_sample_exam/sample_exam_sols/sols.html)
- [Sample Tidyverse Exam 2](https://education.rstudio.com/blog/2020/08/more-example-exams/#tidyverse-exam) \| [solutions](https://tidyverse-exam-v2-solutions.netlify.app/)
-:::
+
-## Teaching Exam `r fontawesome::fa("user-graduate")`
+
+### Teaching Exam `r fontawesome::fa("user-graduate")`
The first certification exam assesses pedagogical skills related to teaching data science with R and requires giving a 15-minute demonstration lesson on a topic of your choice followed by a series of applied questions, which will likely involve creating formative assessments on unseen material (e.g. multiple choice questions and fill-in-the-blank coding exercises), developing concept maps on data science topics and giving feedback on example teaching based on pedagogical theory.
-::: {.note}
+
There are also sample teaching exams available.
- [Sample Teaching Exam 1](https://education.rstudio.com/blog/2020/02/instructor-certification-exams/#teaching-exam)
- [Sample Teaching Exam 2](https://education.rstudio.com/blog/2020/08/more-example-exams/#teaching-exam)
-:::
-
-### Demonstration Lesson: Example
-*Column-wise operations with `dplyr`: Old and New*
+
-If you'd like to see an example of a demonstration lesson, below are the materials I created for this portion of the teaching exam. I used `penguins` from the [`{palmerpenguins}`](https://allisonhorst.github.io/palmerpenguins/) package as an example data set. (why? because penguins `r emo::ji("penguin")` `r emo::ji("penguin")` `r emo::ji("penguin")`).
+### Example Lesson
-::: {.github}
- You can find all of the materials for this lesson and the accompanying code on [Github](https://github.com/brendanhcullen/rstudio-instructor-certification). Feel free to share, adapt and re-use for your own teaching.
-:::
-
-#### Slides `r fontawesome::fa("film")`
-
-I made heavy use of [Yihui Xie](https://yihui.org/en/about/)'s [`{xaringan}`](https://slides.yihui.org/xaringan/) `r emo::ji("package")`, [Garrick Aden-Buie](https://www.garrickadenbuie.com/)'s [`{xaringanExtra}`](https://pkg.garrickadenbuie.com/xaringanExtra/#/) `r emo::ji("package")`, and [Kelly Bodwin](https://www.kelly-bodwin.com/)'s [`{flair}`](https://kbodwin.github.io/flair/index.html) `r emo::ji("package")`, along with [Allison Horst](https://www.allisonhorst.com/)'s unbeatable [artwork](https://github.com/allisonhorst/stats-illustrations). For an excellent `{xaringan}` tutorial, I recommend you check out [these slides](https://arm.rbind.io/slides/xaringan.html#1), from the R Markdown whisperer herself, [Alison Hill](https://alison.rbind.io/). Note: you absolutely do not have to use `{xaringan}` to make your slides, and if your lesson includes more images than code, another method for delivering your slides might be better.
+If you'd like to see an example of a demonstration lesson, below are the materials I created for this portion of the teaching exam. You can find all of the source code for this lesson on Github. Feel free to share, adapt and re-use for your own teaching.
```{r echo=FALSE}
xaringanExtra::embed_xaringan(
@@ -98,84 +92,22 @@ xaringanExtra::embed_xaringan(
Full slides available [here](https://columnwise-operations-dplyr.netlify.app/).
-
-
- ❖ ❖ ❖
-
-
-
-#### Concept Map `r fontawesome::fa("sitemap")`
-
-```{r echo=FALSE, out.width="150%"}
-knitr::include_graphics("columnwise-operations.png")
-```
-
-For other community-contributed data science concept maps you can use in your teaching and/or lesson prep, see [here](https://github.com/rstudio/concept-maps).
-
-
-
- ❖ ❖ ❖
-
-
-
-#### Learner Persona `r fontawesome::fa("user")`
-
-```{r echo=FALSE}
-knitr::include_graphics("learner_persona.png")
-```
-
-For a list of other example learner personas, see [here](https://rstudio-education.github.io/learner-personas/).
-
-
-
- ❖ ❖ ❖
-
-
-
-#### Formative Assessment `r fontawesome::fa("user-edit")`
-
-I created [these interactive exercises](https://brendancullen.shinyapps.io/columnwise_operations_formative_assessment/) using the [`learnr`](https://rstudio.github.io/learnr/) package, which I highly recommend you check out. It's quite powerful and versatile.
-
-Here's a quick look.
-
-```{r echo=FALSE}
-knitr::include_app("https://brendancullen.shinyapps.io/columnwise_operations_formative_assessment/", height = "500px")
-```
-
------------------------------------------------------------------------
-# The *why*
+## The *why*
-Ok, this might all seem like quite a bit of time and effort. Why go to the trouble of doing this training? In a word, [Greg Wilson](https://third-bit.com/about/).
+Why go to the trouble of doing this training? Here are a few reasons that come to mind.
-Greg, who co-founded the [Software Carpentry](https://software-carpentry.org/), has over 35 years of experience in education in data science and software engineering, and it shows. He is now part of the [RStudio Education](https://education.rstudio.com/) team, where he runs the the instructor training and certification program. One of the reasons this program stands out is that it benefits from Greg's unique expertise and careful curation of decades of research on evidence-based teaching methods that he has translated into clear and actionable advice. I can guarantee that you will learn a LOT from him.
-
-Greg's most important [advice for teaching](https://third-bit.com/10rules/#teaching), in my opinion:
-
-> "Be kind: all else is details."
-
-**Now, here are some other reasons why you should do this training...**
-
-## Surge in online teaching `r fontawesome::fa("cloud")`
+### Surge in online teaching `r fontawesome::fa("cloud")`
Interest in data science education seems to be ever-increasing. The fact that COVID-19 has forced most education to go online might actually present an opportunity to meet this demand in a more scalable and (hopefully more accessible way that doesn't incur the traditional limitations of travel costs or room capacity. Of course, online education comes with a host of inherent challenges. The training course includes a [whole section](https://docs.google.com/presentation/d/1kbYaHv47Vt59JxqXF7U7pQl5XOwsctzpP740iVM7Bc8/edit#slide=id.g55ddde1eae_0_2) on this. I also recommend you check out this [RStudio webinar](https://rstudio.com/resources/webinars/teaching-online-at-short-notice/) and accompanying [blog post](https://education.rstudio.com/blog/2020/03/teaching-online-on-short-notice/) along with answers to some [frequently asked questions](https://education.rstudio.com/blog/2020/03/online-teaching-qa/) about teaching online.
As online data science education is becoming increasingly the norm, it seems natural to assume that there will be a need for more certified instructors to meet the growing demand.
-
-
- ❖ ❖ ❖
-
-
-
-## Teaching resources galore `r fontawesome::fa("gem")`
+### Teaching resources galore `r fontawesome::fa("gem")`
Another great reason to become a certified instructor is that, as a data science educator, you have a huge and ever-increasing bank of resources at your disposal. What's more, as a certified instructor, you are eligible for free licenses to [RStudio Pro products](https://rstudio.com/products/) and a significant discount for [RStudio Cloud](https://rstudio.cloud/). Here are just some of the great teaching tools from RStudio and the \#rstats community.
-::: {.bookmark}
- The [RStudio Education Blog](https://education.rstudio.com/blog/) is a `r emo::ji("gem")` TREASURE TROVE `r emo::ji("gem")` of resources. Add it to your bookmarks immediately.
-:::
-
**Teaching with RStudio Cloud**
- [webinar](https://rstudio.com/resources/webinars/teaching-r-online-with-rstudio-cloud/) and accompanying [blog post](https://education.rstudio.com/blog/2020/04/teaching-with-rstudio-cloud-q-a/), courtesy of [Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
@@ -204,87 +136,30 @@ Another great reason to become a certified instructor is that, as a data science
- a [book-in-progress](https://rstudio4edu.github.io/rstudio4edu-book/), courtesy of [Desirée De Leon](https://desiree.rbind.io/) and [Alison Hill](https://alison.rbind.io/). This is in a category of its own because it's an absolute gold mine.
-
-
- ❖ ❖ ❖
-
-
-
-## Tried and tested `r fontawesome::fa("comments")`
+### Tried and tested `r fontawesome::fa("comments")`
The instructor training program started back in February 2019 and [as of August 2020](https://education.rstudio.com/blog/2020/08/august-2020-instructors/) there are almost 150 certified tidyverse instructors and 20 shiny instructors. This means that the program has gone through multiple iterations and has made data-driven improvements based on [feedback from participants](https://education.rstudio.com/blog/2020/07/instructor-certification-findings/) -- especially in the realm of supporting online teaching in the aftermath of COVID-19. So you can rest assured that, while it is still a relatively new program, all the kinks have been worked out.
-Plus, I'm sure that the content and structure of the training will continue to adapt to the needs and priorities of the community, and you might even be lucky enough to catch a special guest presentation. For example...
-
-
-
-
-
-
-
-Enjoyed sharing some tips today on "Teaching in Production" for our [@RStudioEDU] certified-instructors-to-be (another [@thomas_mock] distill success story!)
-
---- Alison Presmanes Hill ([@apreshill]) August 20, 2020
-
-
-
-```{=html}
-
-```
-
-
-
-
- ❖ ❖ ❖
-
-
-
-## A focus on inclusivity `r fontawesome::fa("hands-helping")`
+### A focus on inclusivity `r fontawesome::fa("hands-helping")`
The focus of this training is not technical competency -- it's how be an effective teacher. One of the most critical components of teaching effectively is to be inclusive of all learners, regardless of race, religion, sexual orientation, gender identity, disability, etc.
The [\#rstats learning community](https://twitter.com/R4DScommunity) is known for being welcoming and inclusive, so it's no surprise that the training course emphasizes these values as well. What I appreciate most about this aspect of the training is that it will challenge you to think about questions and hypothetical scenarios to which there are no easy answers.
-However, it is extremely important to be pushed out of your comfort zone to consciously and proactively reflect on how you will confront issues such as systemic racism and institutionalized violence against BIPOC communities, sexism and a deeply ingrained culture of sexual harassment. These issues will inevitably arise in one form or another in your classroom or teaching setting, and it's absolutely necessary that we confront these challenges now more than ever. Check out [this slide](https://docs.google.com/presentation/d/1uYQCbs88aao7Ho4d4mUfYi6hOXhgHWV6noR_-jOaE50/edit#slide=id.g56df7927dc_0_1) and [this talk](https://www.youtube.com/watch?v=EhNisFJPfrs) on effective allyship when you get a chance.
+However, it is important to be pushed out of your comfort zone to consciously and proactively reflect on how you will confront issues such as systemic racism and institutionalized violence against BIPOC communities, sexism and a deeply ingrained culture of sexual harassment. These issues will inevitably arise in one form or another in your classroom or teaching setting, and it's necessary that we confront these challenges now more than ever. Check out [this slide](https://docs.google.com/presentation/d/1uYQCbs88aao7Ho4d4mUfYi6hOXhgHWV6noR_-jOaE50/edit#slide=id.g56df7927dc_0_1) and [this talk](https://www.youtube.com/watch?v=EhNisFJPfrs) on effective allyship when you get a chance.
-::: {.book}
- For further reading on inclusivity and social justice in data science education, I recommend you read [this post](https://education.rstudio.com/blog/2020/06/native-classroom/) by [Nicole Thompson Gonzalez](http://www.nicolethompsongonzalez.com/) and [this one](https://medium.com/@yimregister/10-ways-to-integrate-social-justice-into-teaching-data-science-f48d13f2337c) by [Yim Register](http://students.washington.edu/yreg/). Also check out the amazing work that [JooYoung Seo](https://jooyoungseo.com/), the first blind RStudio Certified Instructor, has been doing to make data science tools [more accessible](https://education.rstudio.com/blog/2020/07/a11y-midterm/).
-:::
+
+For further reading on inclusivity and social justice in data science education, I recommend you read this post by Nicole Thompson Gonzalez. Also check out the work that JooYoung Seo has been doing to make data science tools more accessible.
+
Another exciting feature is that the training materials are now [available in Spanish](https://drive.google.com/drive/folders/1qwTEMqoqphF9qu7f0lSCSTmikIf5chBi), courtesy of [Laura Acion](https://lacion.rbind.io/), and hopefully other languages soon, as interest in the training seems to be growing around the world. A similar ongoing project to check out is [`glosario`](https://carpentries.github.io/glosario/), an open source glossary of data science terms translated in multiple languages that can be used for teaching (read more [here](https://education.rstudio.com/blog/2020/07/announcing-glosario/)).
-
-
- ❖ ❖ ❖
-
-
-
-## Community of practice `r fontawesome::fa("users")`
+### Community of practice `r fontawesome::fa("users")`
To extend the idea of including *everyone* who wants to learn data science, we must be active in building teaching communities that extend beyond just the walls of academic institutions.
-RStudio's [mission](https://education.rstudio.com/teach/#:~:text=RStudio's%20mission%20is%20to%20equip,economy%20that%20rewards%20data%20literacy.&text=All%20of%20RStudio's%20resources%20are,materials%20in%20their%20own%20ways.) is to
+RStudio's [mission](https://education.rstudio.com/teach/) is to
> "equip everyone, regardless of means, to participate in a global economy that rewards data literacy."
A more concrete goal, put forth by [Carl Howe](https://education.rstudio.com/trainers/people/howe+carl/), Director of Education at RStudio, is to train the [next million R users](https://rstudio.com/resources/rstudioconf-2019/the-next-million-r-users/). In becoming an RStudio certified instructor, you can better position yourself to actively participate in reaching this goal. But it's worth reflecting on the fact that teaching and learning doesn't happen in a vacuum -- this is where the idea of community comes in. In my opinion, the fact that R users around the world already have a strong sense of community will make it that much easier to welcome new learners into the fold and make it more likely that they themselves will start to train others one day.
-
-::: {.book}
- Read more about building a community of practice [here](https://teachtogether.tech/en/index.html#s:community).
-:::
-
-------------------------------------------------------------------------
-
-*P.S.* If you need yet another reason to do this training, you get a fancy certificate at the end. `r emo::ji("sparkles")`
-
-![](certificate.png)
-
-------------------------------------------------------------------------
-
-# Get in touch
-
-Please feel free to [reach out](https://twitter.com/_bcullen) if you are thinking of participating in the training yourself and want to hear more from someone who's gone through it recently. I would be glad to chat any time!
-
-![](https://media.giphy.com/media/3o7btQsLqXMJAPu6Na/giphy.gif)
diff --git a/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.markdown b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.markdown
new file mode 100644
index 0000000..0575297
--- /dev/null
+++ b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index.markdown
@@ -0,0 +1,165 @@
+---
+title: Reflections on RStudio Instructor Training
+layout: single
+author: Brendan Cullen
+date: '2020-09-03'
+slug: []
+categories: []
+tags:
+ - data science
+ - education
+ - R
+subtitle: ''
+summary: "The 'what' and 'why' of RStudio Instructor Training and resources for those interested in pursuing it."
+authors: []
+lastmod: ''
+featured: no
+image:
+ caption: 'Photo by oatawa on iStock'
+ focal_point: ''
+ preview_only: no
+projects: []
+---
+
+
+
+
+
+
+
+A while back I wrote about how we [need more data science training](https://bcullen.rbind.io/post/2020-03-08-data-science-training-needs-in-grad-school/) as grad students in psychology and that one of the best ways for us to get this training is to [learn from each other](https://twitter.com/_bcullen/status/1237414725081653249). This is just one of many reasons why I'm so humbled and excited to have recently become an [RStudio Certified Instructor](https://education.rstudio.com/trainers/people/cullen+brendan/) in the tidyverse.
+
+I'm looking forward to start implementing and sharing what I learned with my fellow grad students, especially at the end of this month when I will be leading an introductory R workshop for the new cohort of first year PhD and master's students in my department.
+
+As a small way of paying it forward, I wanted to offer a reflection on what I think makes this training so unique and worthwhile along with a summary of what's involved and some resources for those who might be interested in knowing more.
+
+------------------------------------------------------------------------
+
+## The *what*
+
+
+The best place the start is to read about the RStudio Instructor Training and Certification Program here. The RStudio Education Blog also has lots of helpful posts about the program.
+
+
+The process boils down to three steps.
+
+### Training Course
+
+The first step is to sign up for the training course, which will likely be held over Zoom and chunked into 3-4 hour segments across 2-3 days. You can access the training materials [here](https://drive.google.com/drive/folders/13ohFt3D0EJ5PDbMaWTxnHH-hwA7G0IvY).
+
+The training course is an interactive introduction to applying evidence-based teaching methods to data science education, such as [learner personas](https://docs.google.com/presentation/d/1aOnX-B9XlAzkrlIeZa5db3_X2Dk8cS27k3klvPn1SQI/edit), [concept maps](https://docs.google.com/presentation/d/1k45SqyM-w4DtK7dmedeX7pk_r8B9Aq0FKKCxC04pTRM/edit), and [formative assessment](https://docs.google.com/presentation/d/1PBxBFpkB4w-C3_l2rWdGMtjxaxDeu8gVP0K0CHJfbdQ/edit) (i.e. short, diagnostic questions or exercises to figure out if learners are forming accurate mental models). The course also covers how to design teaching materials with [reverse instructional design](https://docs.google.com/presentation/d/1PBxBFpkB4w-C3_l2rWdGMtjxaxDeu8gVP0K0CHJfbdQ/edit#slide=id.g5501944768_0_197) that takes into account [cognitive load](https://docs.google.com/presentation/d/1t9QTkRfGP9WYQjiXoaVAuceFe3ySVe_wLT7j2MYC8bE/edit#slide=id.g39e398e252_0_14), [multiple learning strategies](https://docs.google.com/presentation/d/1bq599QkDdaWXmw-B8JM5jwdl5In9O-NTxLPT2iES0vY/edit#slide=id.g5479673425_0_87), and issues of [inclusivity and student motivation](https://docs.google.com/presentation/d/1uYQCbs88aao7Ho4d4mUfYi6hOXhgHWV6noR_-jOaE50/edit) in the classroom.
+
+
+
+### Technical Exam
+
+The technical exam assesses your proficiency in whatever topic for which you are attempting to become a certified instructor. Currently there are options to become a certified instructor in [tidyverse](https://www.tidyverse.org/) and [shiny](https://shiny.rstudio.com/), and each has its own accompanying technical exam.
+
+I took the tidyverse exam, which, broadly speaking, consists of a series of live coding challenges related to using core tidyverse packages for data cleaning and wrangling, data visualization, string manipulation, functional programming, basic statistical modeling, and creating reproducible documents with R Markdown.
+
+As many others have suggested, a great way to prepare for this exam is to work through the exercises [R for Data Science](https://r4ds.had.co.nz/), particularly for topics that feel rusty to you, and review the community-contributed [solutions](https://jrnold.github.io/r4ds-exercise-solutions/).
+
+
+I highly recommend going through these sample exams from the RStudio Education Blog start to finish to get a sense of what you might need to review.
+
+- [Sample Tidyverse Exam 1](https://education.rstudio.com/blog/2020/02/instructor-certification-exams/#tidyverse-certification-exam) \| [solutions](https://marlycormar.github.io/tidyverse_sample_exam/sample_exam_sols/sols.html)
+- [Sample Tidyverse Exam 2](https://education.rstudio.com/blog/2020/08/more-example-exams/#tidyverse-exam) \| [solutions](https://tidyverse-exam-v2-solutions.netlify.app/)
+
+
+
+
+
+### Teaching Exam
+
+The first certification exam assesses pedagogical skills related to teaching data science with R and requires giving a 15-minute demonstration lesson on a topic of your choice followed by a series of applied questions, which will likely involve creating formative assessments on unseen material (e.g. multiple choice questions and fill-in-the-blank coding exercises), developing concept maps on data science topics and giving feedback on example teaching based on pedagogical theory.
+
+
+There are also sample teaching exams available.
+
+- [Sample Teaching Exam 1](https://education.rstudio.com/blog/2020/02/instructor-certification-exams/#teaching-exam)
+- [Sample Teaching Exam 2](https://education.rstudio.com/blog/2020/08/more-example-exams/#teaching-exam)
+
+
+
+### Example Lesson
+
+If you'd like to see an example of a demonstration lesson, below are the materials I created for this portion of the teaching exam. You can find all of the source code for this lesson on Github. Feel free to share, adapt and re-use for your own teaching.
+
+
+
+
+
+
+Full slides available [here](https://columnwise-operations-dplyr.netlify.app/).
+
+------------------------------------------------------------------------
+
+## The *why*
+
+Why go to the trouble of doing this training? Here are a few reasons that come to mind.
+
+### Surge in online teaching
+
+Interest in data science education seems to be ever-increasing. The fact that COVID-19 has forced most education to go online might actually present an opportunity to meet this demand in a more scalable and (hopefully more accessible way that doesn't incur the traditional limitations of travel costs or room capacity. Of course, online education comes with a host of inherent challenges. The training course includes a [whole section](https://docs.google.com/presentation/d/1kbYaHv47Vt59JxqXF7U7pQl5XOwsctzpP740iVM7Bc8/edit#slide=id.g55ddde1eae_0_2) on this. I also recommend you check out this [RStudio webinar](https://rstudio.com/resources/webinars/teaching-online-at-short-notice/) and accompanying [blog post](https://education.rstudio.com/blog/2020/03/teaching-online-on-short-notice/) along with answers to some [frequently asked questions](https://education.rstudio.com/blog/2020/03/online-teaching-qa/) about teaching online.
+
+As online data science education is becoming increasingly the norm, it seems natural to assume that there will be a need for more certified instructors to meet the growing demand.
+
+### Teaching resources galore
+
+Another great reason to become a certified instructor is that, as a data science educator, you have a huge and ever-increasing bank of resources at your disposal. What's more, as a certified instructor, you are eligible for free licenses to [RStudio Pro products](https://rstudio.com/products/) and a significant discount for [RStudio Cloud](https://rstudio.cloud/). Here are just some of the great teaching tools from RStudio and the \#rstats community.
+
+**Teaching with RStudio Cloud**
+
+- [webinar](https://rstudio.com/resources/webinars/teaching-r-online-with-rstudio-cloud/) and accompanying [blog post](https://education.rstudio.com/blog/2020/04/teaching-with-rstudio-cloud-q-a/), courtesy of [Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
+
+**Interactive lessons with `learnr`**
+
+- [tutorial and demonstration](https://education.rstudio.com/blog/2020/05/learnr-for-remote/), courtesy of [Allison Horst](https://www.allisonhorst.com/)
+
+- [lessons learned](https://education.rstudio.com/blog/2020/06/summer-camp-hs/) from using `learnr` to teach high schoolers, courtesy of [Ezgi Karaesmen](https://www.ezgikaraesmen.com/)
+
+- [a deep dive](https://education.rstudio.com/blog/2020/07/learning-learnr/) into `learnr`, courtesy of [Nischal Shrestha](http://nischalshrestha.me/)
+
+- [{gradethis} package](https://rstudio-education.github.io/gradethis/) for easily grading `learnr` exercises
+
+**Openly licensed teaching materials**
+
+- [a thorough summary](https://education.rstudio.com/blog/2020/05/remote-roundup/) of recent online courses/workshops, courtesy of [Alison Hill](https://alison.rbind.io/)
+
+- [Data Science in a Box](https://datasciencebox.org/), courtesy of [Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
+
+- [STAT 545](https://stat545.com/), courtesy of [Jenny Bryan](https://jennybryan.org/about/)
+
+- [Many others](https://education.rstudio.com/teach/materials/#workshops), courtesy of the RStudio Education Team
+
+**rstudio4edu**
+
+- a [book-in-progress](https://rstudio4edu.github.io/rstudio4edu-book/), courtesy of [Desirée De Leon](https://desiree.rbind.io/) and [Alison Hill](https://alison.rbind.io/). This is in a category of its own because it's an absolute gold mine.
+
+### Tried and tested
+
+The instructor training program started back in February 2019 and [as of August 2020](https://education.rstudio.com/blog/2020/08/august-2020-instructors/) there are almost 150 certified tidyverse instructors and 20 shiny instructors. This means that the program has gone through multiple iterations and has made data-driven improvements based on [feedback from participants](https://education.rstudio.com/blog/2020/07/instructor-certification-findings/) -- especially in the realm of supporting online teaching in the aftermath of COVID-19. So you can rest assured that, while it is still a relatively new program, all the kinks have been worked out.
+
+### A focus on inclusivity
+
+The focus of this training is not technical competency -- it's how be an effective teacher. One of the most critical components of teaching effectively is to be inclusive of all learners, regardless of race, religion, sexual orientation, gender identity, disability, etc.
+
+The [\#rstats learning community](https://twitter.com/R4DScommunity) is known for being welcoming and inclusive, so it's no surprise that the training course emphasizes these values as well. What I appreciate most about this aspect of the training is that it will challenge you to think about questions and hypothetical scenarios to which there are no easy answers.
+
+However, it is important to be pushed out of your comfort zone to consciously and proactively reflect on how you will confront issues such as systemic racism and institutionalized violence against BIPOC communities, sexism and a deeply ingrained culture of sexual harassment. These issues will inevitably arise in one form or another in your classroom or teaching setting, and it's necessary that we confront these challenges now more than ever. Check out [this slide](https://docs.google.com/presentation/d/1uYQCbs88aao7Ho4d4mUfYi6hOXhgHWV6noR_-jOaE50/edit#slide=id.g56df7927dc_0_1) and [this talk](https://www.youtube.com/watch?v=EhNisFJPfrs) on effective allyship when you get a chance.
+
+
+For further reading on inclusivity and social justice in data science education, I recommend you read this post by Nicole Thompson Gonzalez. Also check out the work that JooYoung Seo has been doing to make data science tools more accessible.
+
+
+Another exciting feature is that the training materials are now [available in Spanish](https://drive.google.com/drive/folders/1qwTEMqoqphF9qu7f0lSCSTmikIf5chBi), courtesy of [Laura Acion](https://lacion.rbind.io/), and hopefully other languages soon, as interest in the training seems to be growing around the world. A similar ongoing project to check out is [`glosario`](https://carpentries.github.io/glosario/), an open source glossary of data science terms translated in multiple languages that can be used for teaching (read more [here](https://education.rstudio.com/blog/2020/07/announcing-glosario/)).
+
+### Community of practice
+
+To extend the idea of including *everyone* who wants to learn data science, we must be active in building teaching communities that extend beyond just the walls of academic institutions.
+
+RStudio's [mission](https://education.rstudio.com/teach/) is to
+
+> "equip everyone, regardless of means, to participate in a global economy that rewards data literacy."
+
+A more concrete goal, put forth by [Carl Howe](https://education.rstudio.com/trainers/people/howe+carl/), Director of Education at RStudio, is to train the [next million R users](https://rstudio.com/resources/rstudioconf-2019/the-next-million-r-users/). In becoming an RStudio certified instructor, you can better position yourself to actively participate in reaching this goal. But it's worth reflecting on the fact that teaching and learning doesn't happen in a vacuum -- this is where the idea of community comes in. In my opinion, the fact that R users around the world already have a strong sense of community will make it that much easier to welcome new learners into the fold and make it more likely that they themselves will start to train others one day.
diff --git a/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/fitvids/fitvids.min.js b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/fitvids/fitvids.min.js
new file mode 100644
index 0000000..9c25d2d
--- /dev/null
+++ b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/fitvids/fitvids.min.js
@@ -0,0 +1 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.fitvids=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0?ignored.join():null;var selector=selectors.concat(custom).join();if(!hasLength(selector)){return}containers.forEach(function(container){var videos=queryAll(container,selector);videos.forEach(function(video){if(ignoredSelector&&video.matches(ignoredSelector)){return}wrap(video)})})};function queryAll(el,selector){if(typeof el==="string"){selector=el;el=document}return Array.prototype.slice.call(el.querySelectorAll(selector))}function toSelectorArray(input){if(typeof input==="string"){return input.split(",").map(trim).filter(hasLength)}else if(isArray(input)){return flatten(input.map(toSelectorArray).filter(hasLength))}return input||[]}function wrap(el){if(/fluid-width-video-wrapper/.test(el.parentNode.className)){return}var widthAttr=parseInt(el.getAttribute("width"),10);var heightAttr=parseInt(el.getAttribute("height"),10);var width=!isNaN(widthAttr)?widthAttr:el.clientWidth;var height=!isNaN(heightAttr)?heightAttr:el.clientHeight;var aspect=height/width;el.removeAttribute("width");el.removeAttribute("height");var wrapper=document.createElement("div");el.parentNode.insertBefore(wrapper,el);wrapper.className="fluid-width-video-wrapper";wrapper.style.paddingTop=aspect*100+"%";wrapper.appendChild(el)}function styles(){var div=document.createElement("div");div.innerHTML='
x
";return div.childNodes[1]}function hasLength(input){return input.length>0}function trim(str){return str.replace(/^\s+|\s+$/g,"")}function flatten(input){return[].concat.apply([],input)}function isObject(input){return Object.prototype.toString.call(input)==="[object Object]"}function isArray(input){return Object.prototype.toString.call(input)==="[object Array]"}},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/header-attrs/header-attrs.js b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/header-attrs/header-attrs.js
new file mode 100644
index 0000000..dd57d92
--- /dev/null
+++ b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/index_files/header-attrs/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/content/post/2020-09-03-reflections-on-rstudio-instructor-training/learner_persona.png b/content/blog/2020-09-03-reflections-on-rstudio-instructor-training/learner_persona.png
similarity index 100%
rename from content/post/2020-09-03-reflections-on-rstudio-instructor-training/learner_persona.png
rename to content/blog/2020-09-03-reflections-on-rstudio-instructor-training/learner_persona.png
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/countdown.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/countdown.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/countdown.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/countdown.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/data_sci_specialization.jpg b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/data_sci_specialization.jpg
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/data_sci_specialization.jpg
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/data_sci_specialization.jpg
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/extra_style.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/extra_style.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/extra_style.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/extra_style.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/featured.jpg b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/featured.jpg
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/featured.jpg
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/featured.jpg
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/flipbook.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/flipbook.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/flipbook.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/flipbook.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmd b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmarkdown
similarity index 77%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmd
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmarkdown
index ef71190..30c8902 100644
--- a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmd
+++ b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.Rmarkdown
@@ -1,70 +1,64 @@
---
title: "Flattening the leaRning curve: Teaching R online during COVID-19"
-author: Brendan Cullen
-date: '2020-10-19'
-slug: []
-categories: []
+subtitle: ""
+summary: "Lessons learned from my first experience teaching an R bootcamp remotely & a collection of tools and resources I found useful"
+date: 2020-10-19
+author: "Brendan Cullen"
+draft: false
+images:
+series:
tags:
- - data science
- - education
- R
-subtitle: ''
-summary: 'Lessons learned from my first experience teaching an R bootcamp remotely & a collection of tools and resources I found useful'
-authors: []
-lastmod: '2020-10-19T10:26:32-07:00'
-featured: no
-image:
- caption: 'Photo by Martin Adams on Unsplash'
- focal_point: ''
- preview_only: no
-projects: []
-disable_codefolding: false
-codefolding_show: "hide"
-codefolding_nobutton: false
+ - tidyverse
+ - education
+categories:
+layout: single
---
+
+
+
+
+
```{r echo=FALSE, message=FALSE}
library(tidyverse)
library(Manu)
library(xaringanExtra)
-
-# enable panelset
-use_panelset()
```
At this point, you’re probably familiar with the phrase “flatten the curve” — remember back in March when we were all talking about that? It was part of a critical public health messaging campaign aimed at slowing the spread of COVID-19 to prevent hospitals from becoming overwhelmed beyond their capacity. Based on how things are going, we really should *still* be talking about that. So allow me to unabashedly steal this catchphrase as a flawed metaphor for teaching and learning R during the era of this pandemic...
It’s no secret that R has a significant leaRning curve — and, while it seems that more people than ever are now wanting to learn R, almost everyone is having to do it in an online format of some kind. For those who are used to a traditional in-person classroom environment, having a first introduction to R in an online format might make the leaRning curve even steeper (as I said, a flawed metaphor -- the concept of a "steep learning curve" is actually the [opposite](https://www.valamis.com/hub/learning-curve#steep-learning-curve) of what most people think, but we’ll run with it anyway). After recently teaching an introductory [R Bootcamp](https://uopsych-r-bootcamp-2020.netlify.app/) online, I've spent a lot of time thinking about strategies to lower the learning threshold and make it easier to conquer any potential fear of learning R -- to "flatten the leaRning curve", as it were.
-:::reader
+
For anyone who might be new to teaching R, teaching online, or both, the goal of this post is to share some valuable lessons I learned and resources I used during this online teaching experience. I hope it may be of some benefit for your own teaching.
-:::
+
-# Background
+## Background
Back in Fall 2018, the Department of Psychology at the University of Oregon started to offer a grad-student-led introductory R Bootcamp the week before the start of the new academic year. The bootcamp consists of three 3-4 hour sessions that take place over the course of a week. The idea behind the bootcamp is to give a first exposure to R to incoming students who have little to no background in it before being launched headfirst into using R to analyze data for their first year project and to complete labs and homework assignments for [PSY611](https://uopsych.github.io/psy611/), the first in a series of graduate statistics courses taught entirely in R.
In addition, as I've [written about previously](/post/2020-03-08-data-science-training-needs-in-grad-school/index.html), current grad students, along with other members of the psychology department, have expressed a keen interest in developing a stronger foundation in skills such as basic programming, data wrangling, and data visualization. So the bootcamp also serves as an opportunity for existing R users to get a refresher and deeper dive into those topics for those who want it.
-After spending lot of time thinking about how to improve the data science learning experience for my fellow grad students and having [recently become](https://bcullen.rbind.io/post/2020-09-03-reflections-on-rstudio-instructor-training/) an [RStudio Certified Instructor](https://education.rstudio.com/trainers/people/cullen+brendan/) in the tidyverse, it was my great privilege to be able to put all of this into action by leading the 3rd Annual UO Psych Bootcamp this year. `r emo::ji("partying_face")`
+After spending lot of time thinking about how to improve the data science learning experience for my fellow grad students and having [recently become](https://bcullen.rbind.io/post/2020-09-03-reflections-on-rstudio-instructor-training/) an [RStudio Certified Instructor](https://education.rstudio.com/trainers/people/cullen+brendan/) in the tidyverse, it was my great privilege to be able to put all of this into action by leading the 3rd Annual UO Psych Bootcamp this year.
-# The challenge
+### The challenge
However, I found myself facing a rather significant challenge. The R Bootcamp, like many intro R workshops, usually occurs in-person in a large room with a giant projector screen, coffee and snacks, and, most importantly, the ability to run over and look over someone's shoulder at their computer screen when they need help. Because of COVID-19, I needed to design and deliver a bootcamp for a large group of beginners (many using R for the very first time) entirely over a webcam.
Moreover, I assumed that student motivation would be at an all-time low and feelings of anxiety and uncertainty would be at an all-time high -- especially for those about to start their graduate school journey entirely online, very much contrary to plan. There were a lot of horrible things going on in the world in September 2020, which marked 6 months into the COVID-19 pandemic in the U.S. -- people's loved ones were getting sick, the killing of innocent Black lives continued, a bitter presidential race reached full swing -- not to mention devastating wildfires that raged all along the west coast. (Of course, while I wish I could actually write about these events in the past tense, all of these problems continue).
-So, how do you get people excited about learning R amidst all of *that*? Needless to say, this felt a little daunting `r emo::ji("fearful")`. Fortunately, though, there are people out there who are experts in this sort of thing who have graciously shared their resources and advice, and this helped me immensely to run a successful bootcamp.
+So, how do you get people excited about learning R amidst all of *that*? Needless to say, this felt a little daunting. Fortunately, though, there are people out there who are experts in this sort of thing who have graciously shared their resources and advice, and this helped me immensely to run a successful bootcamp.
-# Who attended?
+### Who attended?
52 people registered for the bootcamp. While the majority of those who attended were incoming first-year psychology grad students, we also had a mix of more advanced grad students, undergrads, research assistants, lab managers, staff data analysts, and faculty members from a variety of departments/centers across the University, including the Departments of Psychology, Linguistics, Economics and the Center for Translational Neuroscience.
-```{r, warning=FALSE, message=FALSE}
-# import bootcamp registration data
+```{r echo=FALSE, warning=FALSE, message=FALSE}
+## import bootcamp registration data
registration <- read_csv("uopsych_bootcamp_registration_deidentified.csv")
-# clean data
+## clean data
plot_data <- registration %>%
janitor::clean_names() %>%
select(position = what_is_your_position_at_uo,
@@ -79,7 +73,7 @@ plot_data <- registration %>%
"I've used it to analyze data",
"I use it often to analyze data")))
-# plot positions at UO
+## plot positions at UO
theme_set(theme_minimal(base_size = 15))
theme_update(legend.position = "none",
plot.title.position = "plot",
@@ -94,9 +88,10 @@ plot_data %>%
labs(x = "", y = "Count", title = "Participants' roles at University of Oregon")
```
+
-```{r}
-# plot prior experience
+```{r echo=FALSE}
+## plot prior experience
plot_data %>%
count(experience) %>%
ggplot(aes(experience, n, fill = experience)) +
@@ -106,9 +101,9 @@ plot_data %>%
labs(x = "", y = "Count", title = "Participants' prior experience with R")
```
-# Logistics
+### Logistics
-## Zoom + Slack = `r emo::ji("ok_hand")`
+#### Zoom + Slack = `r emo::ji("ok_hand")`
We ran synchronous sessions live over Zoom. However, rather than use the Zoom chat for communicating with each other and asking questions, we used Slack. A few reasons for this:
@@ -120,11 +115,11 @@ We ran synchronous sessions live over Zoom. However, rather than use the Zoom ch
I was fortunate to have the very knowledgeable and talented [Cameron Kay](http://cameronstuartkay.com/) and [Cianna Bedford-Petersen](https://ciannabp.com/) as teaching assistants. Cam and Cianna remained on deck throughout the sessions to answer questions on Slack while we went through the material. We also decided that if a student ran into technical issues or felt completely lost, then one of the TA's would pull them into a breakout room on Zoom to offer one-on-one help.
-## RStudio Cloud
+#### RStudio Cloud
For "Your Turn" exercises, an idea I stole from Alison Hill's excellent rstudio::conf(2020) [workshop](https://conf20-intro-ml.netlify.app/), we used [RStudio Cloud](https://rstudio.com/products/cloud/), a hosted version of the RStudio IDE available in the web browser. We did this to avoid issues with students installing RStudio on their local machines, as troubleshooting technical issues over Zoom in a large group is not something we felt prepared for. Using RStudio Cloud also allowed me to configure specific IDE settings and pre-load specific packages to allow students to initially avoid technical issues. Lastly, sharing a workspace on RStudio Cloud allowed each student to save their own copy of the projects containing the Your Turn exercises, which in turn made it possible for myself or the TA's to "peek" into a student's exercises and help them figure out where their errors were coming from. Overall it went really smoothly, and everyone who filled out the feedback survey said they had no issues using it. I highly recommend using this for your teaching, even if it's in-person.
-## Blogdown site
+#### Blogdown site
To make the bootcamp materials more accessible and shareable, I decided to package them into a website, which I created using the [blogdown](https://github.com/rstudio/blogdown) package (see more on this [below](#ssn)). Organizing your teaching materials into a website has three clear advantages in my mind:
@@ -132,7 +127,7 @@ To make the bootcamp materials more accessible and shareable, I decided to packa
2) A website is highly sustainable in the sense that it's easy for students to bookmark and refer back to over and over, and if you push changes to Github with continuous deployment (e.g. via [Netlify](https://www.netlify.com/)), students will always have access to the most updated materials. This avoids having to introduce Github and version control, which is a whole other beast to teach to beginners.
-3) Websites are pretty and highly customizble `r emo::ji("sparkles")`
+3) Websites are pretty and highly customizble
`r emo::ji("link")` [uopsych-r-bootcamp-2020.netlify.app](https://uopsych-r-bootcamp-2020.netlify.app/)
@@ -141,11 +136,10 @@ knitr::include_url("https://uopsych-r-bootcamp-2020.netlify.app/", height = "500
```
-# Tools I learned {#tools}
+### Tools I learned {#tools}
-:::: {.panelset}
-
-### `xaringanExtra` {.panel}
+{{< panelset class="tools" >}}
+{{< panel name="`xaringanExtra`" >}}
`r emo::ji("package")` [pkg.garrickadenbuie.com/xaringanExtra](https://pkg.garrickadenbuie.com/xaringanExtra/)
@@ -155,27 +149,33 @@ knitr::include_url("https://uopsych-r-bootcamp-2020.netlify.app/", height = "500
`r emo::ji("book")` [Share again](https://pkg.garrickadenbuie.com/xaringanExtra/#/share-again)
-![](share_again.mov)
+
`r emo::ji("book")` [Panelset](https://pkg.garrickadenbuie.com/xaringanExtra/#/panelset)
-![](panelset.mov)
+
`r emo::ji("book")` [Tile view](https://pkg.garrickadenbuie.com/xaringanExtra/#/tile-view)
-![](tile_view.mov)
+
`r emo::ji("book")` [Extra styles](https://pkg.garrickadenbuie.com/xaringanExtra/#/extra-styles)
-![](extra_style.mov)
-
-In case it still isn't obvious enough how much I love this package...
-
-
Ok, {xaringanExtra} continues to blow my freakin' mind 🤯 Here's a quick demo that shows tile view and `embed_xaringan()` in the context of a #ggplot2 flipbook (h/t @EvaMaeRey). @grrrck, I owe you an absurd amount of beers 🍻 Thank you for all you do for the #rstats community 🙌 pic.twitter.com/ucMCbOvopW
+
[Jump back up to see more tools](#tools) `r emo::ji("right_arrow_curving_up")`
-### `flair` {.panel}
+{{< /panel >}}
+
+{{< panel name="`flair`" >}}
`r emo::ji("package")` [r-for-educators.github.io/flair](https://r-for-educators.github.io/flair/index.html)
@@ -193,7 +193,9 @@ You can read more about other educational use cases for `flair` in this great [p
[Jump back up to see more tools](#tools) `r emo::ji("right_arrow_curving_up")`
-### `flipbookr` {.panel}
+{{< /panel >}}
+
+{{< panel name="`flipbookr`" >}}
`r emo::ji("package")` [evamaerey.github.io/flipbooks/about](https://evamaerey.github.io/flipbooks/about)
@@ -201,27 +203,34 @@ You can read more about other educational use cases for `flair` in this great [p
`{flipbookr}` is an amazing teaching tool -- it allows you to incrementally build up a plot line by line, which capitalizes on the "blink comparator" method. This means that students are able to easily map a specific change in code to a specific visual change in the corresponding plot output. Flipbooks are also great for demonstrating incremental changes in a data wrangling pipeline, and they're relatively easy to make!
-![](flipbook.mov)
+
[Jump back up to see more tools](#tools) `r emo::ji("right_arrow_curving_up")`
-### `countdown` {.panel}
+{{< /panel >}}
+
+{{< panel name="`countdown`" >}}
`r emo::ji("package")` [pkg.garrickadenbuie.com/countdown](https://pkg.garrickadenbuie.com/countdown/)
[Garrick Aden-Buie](https://www.garrickadenbuie.com/)
-`{coundown}` is another great gem from Garrick and allows you to put timers directly on your slides. This is really useful for timed "Your Turn" exercises or to make sure you stay on track with Q & A sessions or breaks.
+`{countdown}` is another great gem from Garrick and allows you to put timers directly on your slides. This is really useful for timed "Your Turn" exercises or to make sure you stay on track with Q & A sessions or breaks.
-![](countdown.mov)
+
[Jump back up to see more tools](#tools) `r emo::ji("right_arrow_curving_up")`
-::::
+{{< /panel >}}
+{{< /panelset >}}
-# Resources I recommend
+### Resources I recommend
-## Sharing on short notice {#ssn}
+#### Sharing on short notice {#ssn}
[Alison Hill](https://alison.rbind.io/), [Desirée De Leon](https://desiree.rbind.io/)
@@ -232,7 +241,7 @@ A super helpful webinar on how best to share your teaching materials online.
- [share-blogdown template](https://github.com/apreshill/share-blogdown)
- [blog post](https://education.rstudio.com/blog/2020/04/sharing-on-short-notice/)
-## Teaching online on short notice
+#### Teaching online on short notice
[Greg Wilson](https://third-bit.com/)
@@ -242,7 +251,7 @@ Concrete tips and advice on making the most of teaching via a webcam. There's a
- [slides](https://docs.google.com/presentation/d/1rE5e2kSFNICNkBJ4iIIgd9eqACi62gxahknKLtw9Hzs/edit#slide=id.g55ddde1eae_0_2)
- [blog post](https://education.rstudio.com/blog/2020/03/teaching-online-on-short-notice/)
-## Teaching R online with RStudio Cloud
+#### Teaching R online with RStudio Cloud
[Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
@@ -252,7 +261,7 @@ A very thorough and easy to follow walk-through of using RStudio Cloud for teach
- [slides](https://mine-cetinkaya-rundel.github.io/rstudio-cloud-webinar/rstudio-cloud.html#1)
- [blog post](https://education.rstudio.com/blog/2020/04/teaching-with-rstudio-cloud-q-a/)
-## Teaching the tidyverse in 2020
+#### Teaching the tidyverse in 2020
[Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
@@ -263,7 +272,7 @@ A series of blog posts describing a recommended order in which to teach tidyvers
- [Part 3: Data wrangling and tidying](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-3-data-wrangling-and-tidying/)
- [Part4: Part 4: When to purrr?](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-4-when-to-purrr/)
-## Data science concept maps
+#### Data science concept maps
A growing list of concept maps related to data science topics in R. Great for planning your lessons and/or sharing in your slides to summarize topics, no matter how seemingly simple or complex.
@@ -273,7 +282,7 @@ A growing list of concept maps related to data science topics in R. Great for pl
- [google drive folder](https://docs.google.com/presentation/d/1ForBjP0pVhljBLuqOyYfyHw_1rrwJzpWW1ZHzCqAJpU/edit#slide=id.p)
- [blog post](https://education.rstudio.com/blog/2020/09/concept-maps/)
-## rstats artwork {#artwork}
+#### rstats artwork {#artwork}
[Allison Horst](https://www.allisonhorst.com/)
@@ -282,7 +291,7 @@ A collection of mind-blowing art that makes it 1000% more fun to learn R.
- [github repo](https://github.com/allisonhorst/stats-illustrations)
- [interview with Allison Horst](https://www.dataquest.io/blog/making-learning-to-code-friendlier-with-art-allison-horst-interview/)
-# The importance of encouragement & positivity
+### The importance of encouragement & positivity
The leaRning curve is no secret. I hadn't touched R before starting grad school in 2017, but I had heard whispers here and there that learning R is really difficult. But I think there's an element of self-fulfilling prophecy here. If you expect it to be impossible, then it will feel impossible. I more or less started my journey with that expectation.
@@ -290,15 +299,15 @@ Things changed for me when I took my first course with [Daniel Anderson](https:/
It was very much with Daniel's model in mind that I found inspiration for making learning R feel more inviting and less daunting. Here are a few things that came to mind that can be abstracted to some general advice...
-## Anticipate the challenge
+#### Anticipate the challenge
-Recognize the fact that learning R is *hard*. Don't pretend it's a walk in the park -- it isn't. But at the same time, emphasize that the investment of time it takes is worth it! And be sure to remind people of that more than once `r emo::ji("wink")`.
+Recognize the fact that learning R is *hard*. Don't pretend it's a walk in the park -- it isn't. But at the same time, emphasize that the investment of time it takes is worth it!
```{r echo=FALSE}
xaringanExtra::embed_xaringan("https://uopsych-r-bootcamp-2020.netlify.app/slides/00-slides.html#10")
```
-## Normalize errors & mistakes
+#### Normalize errors & mistakes
The first time someone uses R, error messages are one of the first things that they'll see. As we all know, this feels frustrating, especially as a beginner. So it makes sense to acknowledge that up front and discuss what error messages are and why they occur. As error messages go hand-in-hand with debugging, it's also a good idea to at least introduce that concept as well, without necessarily going into great depth since that's a whole other topic of it's own. As debugging is commonly considered part of ["what they forgot to teach you about R"](https://rstats.wtf/debugging-r-code.html), I'm sure I'm not alone in wishing that I had been introduced to debugging much earlier on in my R learning experience.
@@ -312,12 +321,12 @@ xaringanExtra::embed_xaringan("https://uopsych-r-bootcamp-2020.netlify.app/slide
Taking this one step further, it's a good idea to deliberately incorporate making mistakes into your own teaching and use error messages as a teachable moment. You can even use unintentional mistakes as teachable moments -- demonstrate for your students how you fix the mistake and invite them to give their thoughts and feedback. This not only makes your presentation less rehearsed, but it provides a really valuable "real-world" context for learning.
-:::note
-This idea is referred to as "positive error framing" -- and if you want to learn more about this topic in depth I recommend you check out [this section](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008090#sec011) from the recent article ["Ten quick tips for teaching with participatory live coding"](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008090) (really you should read the whole article -- it's packed full of great advice).
-:::
+
-## Make your materials friendly and inviting!
+### Make your materials friendly and inviting!
If your slides read like one long piece of dense help documentation, people are not going to feel inclined to engage with it. How do you make your materials more inviting and approachable?
@@ -329,43 +338,17 @@ One of the most powerful tools out there, in my opinion, is the incredible artwo
knitr::include_graphics("monster_support.jpg")
```
-Cute gifs never hurt either...
+### A final thought
-
If you're teaching #rstats with #palmerpenguins at the moment (which you should be because it's a brilliant dataset 🐧), consider sneaking in a lil' motivational penguin, both for yourself and your students. everything is terrible and we all need small joys now more than ever pic.twitter.com/OHeJWIsqFp
+No matter how long someone has been using R, it never hurts to remind them (yourself included) that a little time and effort can go a long way.
-# Feedback
-
-I was really happy to see that people seemed to appreciate the positive learning atmosphere and, especially because this was only an introductory workshop, that this made them excited to learn more:
-
-:::quote
-
-`r emo::ji("writing_hand")` "I really appreciated the warm welcome/atmosphere the instructors set up- learning a new programming language can be frustrating, especially for a beginner, so I was really appreciative of the continuous encouragement throughout the bootcamp."
-
-***
-`r emo::ji("writing_hand")` "I really enjoyed how supportive and encouraging the facilitators were. I understood learning R was no easy endeavor but hearing about their experiences was encouraging for me. Also, I greatly appreciate all the amazing resources they have compiled for future use. I definitely plan to continue looking into it!"
-
-***
-`r emo::ji("writing_hand")` "I appreciated the facilitators' organization, support, encouragement, and instructional clarity. Thank you for providing this very warm and accessible introduction for an absolute first-time novice! It's encouraged me to take more steps into learning R."
-
-***
-`r emo::ji("writing_hand")` "I am now in my third year of struggling through R and this was the first presentation of material that really clicked for me. I frequently refer to the dplyr and ggplot presentations in my work and will continue to work my way through these exercises until I am truly fluent in these basics. THANK YOU"
-:::
-
-So we did we flatten the leaRning curve? Only time will tell. But the most gratifying feedback, in my opinion, is that people who attended felt inspired to *keep learning* and continue riding the R roller coaster. That's really the best outcome I could have hoped for!
-
-```{r echo=FALSE}
-knitr::include_graphics("r_rollercoaster.png")
-```
-
-# A final thought
+
-In short, no matter how long someone has been using R, it never hurts to remind them (yourself included) that a little time and effort can go a long way.
+
-
-![](time_effort.gif){width="417"}
-# Acknowledgements
+### Acknowledgements
I owe a huge debt of gratitude to all the people who were instrumental in my initial experience of learning R: [Daniel Anderson](https://twitter.com/datalorax_), [Dani Cosme](https://twitter.com/danicosme), [Krista DeStasio](https://twitter.com/PsychNeurd), [Cory Costello](https://twitter.com/CostelloCK), [Jessica Kosie](https://twitter.com/JessKosie), and [Sara Weston](https://twitter.com/saraweston09), to name only a few.
diff --git a/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.markdown b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.markdown
new file mode 100644
index 0000000..a1e2ef5
--- /dev/null
+++ b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index.markdown
@@ -0,0 +1,476 @@
+---
+title: "Flattening the leaRning curve: Teaching R online during COVID-19"
+subtitle: ""
+summary: "Lessons learned from my first experience teaching an R bootcamp remotely & a collection of tools and resources I found useful"
+date: 2020-10-19
+author: "Brendan Cullen"
+draft: false
+images:
+series:
+tags:
+ - R
+ - tidyverse
+ - education
+categories:
+layout: single
+---
+
+
+
+
+
+
+
+
+
+
+
+At this point, you’re probably familiar with the phrase “flatten the curve” — remember back in March when we were all talking about that? It was part of a critical public health messaging campaign aimed at slowing the spread of COVID-19 to prevent hospitals from becoming overwhelmed beyond their capacity. Based on how things are going, we really should *still* be talking about that. So allow me to unabashedly steal this catchphrase as a flawed metaphor for teaching and learning R during the era of this pandemic...
+
+It’s no secret that R has a significant leaRning curve — and, while it seems that more people than ever are now wanting to learn R, almost everyone is having to do it in an online format of some kind. For those who are used to a traditional in-person classroom environment, having a first introduction to R in an online format might make the leaRning curve even steeper (as I said, a flawed metaphor -- the concept of a "steep learning curve" is actually the [opposite](https://www.valamis.com/hub/learning-curve#steep-learning-curve) of what most people think, but we’ll run with it anyway). After recently teaching an introductory [R Bootcamp](https://uopsych-r-bootcamp-2020.netlify.app/) online, I've spent a lot of time thinking about strategies to lower the learning threshold and make it easier to conquer any potential fear of learning R -- to "flatten the leaRning curve", as it were.
+
+
+For anyone who might be new to teaching R, teaching online, or both, the goal of this post is to share some valuable lessons I learned and resources I used during this online teaching experience. I hope it may be of some benefit for your own teaching.
+
+
+## Background
+
+Back in Fall 2018, the Department of Psychology at the University of Oregon started to offer a grad-student-led introductory R Bootcamp the week before the start of the new academic year. The bootcamp consists of three 3-4 hour sessions that take place over the course of a week. The idea behind the bootcamp is to give a first exposure to R to incoming students who have little to no background in it before being launched headfirst into using R to analyze data for their first year project and to complete labs and homework assignments for [PSY611](https://uopsych.github.io/psy611/), the first in a series of graduate statistics courses taught entirely in R.
+
+In addition, as I've [written about previously](/post/2020-03-08-data-science-training-needs-in-grad-school/index.html), current grad students, along with other members of the psychology department, have expressed a keen interest in developing a stronger foundation in skills such as basic programming, data wrangling, and data visualization. So the bootcamp also serves as an opportunity for existing R users to get a refresher and deeper dive into those topics for those who want it.
+
+After spending lot of time thinking about how to improve the data science learning experience for my fellow grad students and having [recently become](https://bcullen.rbind.io/post/2020-09-03-reflections-on-rstudio-instructor-training/) an [RStudio Certified Instructor](https://education.rstudio.com/trainers/people/cullen+brendan/) in the tidyverse, it was my great privilege to be able to put all of this into action by leading the 3rd Annual UO Psych Bootcamp this year.
+
+### The challenge
+
+However, I found myself facing a rather significant challenge. The R Bootcamp, like many intro R workshops, usually occurs in-person in a large room with a giant projector screen, coffee and snacks, and, most importantly, the ability to run over and look over someone's shoulder at their computer screen when they need help. Because of COVID-19, I needed to design and deliver a bootcamp for a large group of beginners (many using R for the very first time) entirely over a webcam.
+
+Moreover, I assumed that student motivation would be at an all-time low and feelings of anxiety and uncertainty would be at an all-time high -- especially for those about to start their graduate school journey entirely online, very much contrary to plan. There were a lot of horrible things going on in the world in September 2020, which marked 6 months into the COVID-19 pandemic in the U.S. -- people's loved ones were getting sick, the killing of innocent Black lives continued, a bitter presidential race reached full swing -- not to mention devastating wildfires that raged all along the west coast. (Of course, while I wish I could actually write about these events in the past tense, all of these problems continue).
+
+So, how do you get people excited about learning R amidst all of *that*? Needless to say, this felt a little daunting. Fortunately, though, there are people out there who are experts in this sort of thing who have graciously shared their resources and advice, and this helped me immensely to run a successful bootcamp.
+
+### Who attended?
+
+52 people registered for the bootcamp. While the majority of those who attended were incoming first-year psychology grad students, we also had a mix of more advanced grad students, undergrads, research assistants, lab managers, staff data analysts, and faculty members from a variety of departments/centers across the University, including the Departments of Psychology, Linguistics, Economics and the Center for Translational Neuroscience.
+
+
+
+
+
+
+
+### Logistics
+
+#### Zoom + Slack = 👌
+
+We ran synchronous sessions live over Zoom. However, rather than use the Zoom chat for communicating with each other and asking questions, we used Slack. A few reasons for this:
+
+1) this way people could continue to ask questions outside of the live sessions and a permanent and searchable record of questions and answers would be available for posterity
+
+2) The Zoom chat can get easily cluttered and doesn't easily allow you to make threads, which keep things more organized
+
+3) Slack has better emojis 🤓.
+
+I was fortunate to have the very knowledgeable and talented [Cameron Kay](http://cameronstuartkay.com/) and [Cianna Bedford-Petersen](https://ciannabp.com/) as teaching assistants. Cam and Cianna remained on deck throughout the sessions to answer questions on Slack while we went through the material. We also decided that if a student ran into technical issues or felt completely lost, then one of the TA's would pull them into a breakout room on Zoom to offer one-on-one help.
+
+#### RStudio Cloud
+
+For "Your Turn" exercises, an idea I stole from Alison Hill's excellent rstudio::conf(2020) [workshop](https://conf20-intro-ml.netlify.app/), we used [RStudio Cloud](https://rstudio.com/products/cloud/), a hosted version of the RStudio IDE available in the web browser. We did this to avoid issues with students installing RStudio on their local machines, as troubleshooting technical issues over Zoom in a large group is not something we felt prepared for. Using RStudio Cloud also allowed me to configure specific IDE settings and pre-load specific packages to allow students to initially avoid technical issues. Lastly, sharing a workspace on RStudio Cloud allowed each student to save their own copy of the projects containing the Your Turn exercises, which in turn made it possible for myself or the TA's to "peek" into a student's exercises and help them figure out where their errors were coming from. Overall it went really smoothly, and everyone who filled out the feedback survey said they had no issues using it. I highly recommend using this for your teaching, even if it's in-person.
+
+#### Blogdown site
+
+To make the bootcamp materials more accessible and shareable, I decided to package them into a website, which I created using the [blogdown](https://github.com/rstudio/blogdown) package (see more on this [below](#ssn)). Organizing your teaching materials into a website has three clear advantages in my mind:
+
+1) A website makes your materials easier to access and more shareable -- you send someone a single link they can access on their phone or computer, no need to download anything
+
+2) A website is highly sustainable in the sense that it's easy for students to bookmark and refer back to over and over, and if you push changes to Github with continuous deployment (e.g. via [Netlify](https://www.netlify.com/)), students will always have access to the most updated materials. This avoids having to introduce Github and version control, which is a whole other beast to teach to beginners.
+
+3) Websites are pretty and highly customizble
+
+🔗 [uopsych-r-bootcamp-2020.netlify.app](https://uopsych-r-bootcamp-2020.netlify.app/)
+
+
+
+
+### Tools I learned {#tools}
+
+{{< panelset class="tools" >}}
+{{< panel name="`xaringanExtra`" >}}
+
+📦 [pkg.garrickadenbuie.com/xaringanExtra](https://pkg.garrickadenbuie.com/xaringanExtra/)
+
+ [Garrick Aden-Buie](https://www.garrickadenbuie.com/)
+
+`{xaringanExtra}` extends the functionality of the already amazing `{xaringan}` package by [Yihuie Xie](https://yihui.org/en/about/), and it has become one of my all-time favorite packages. Here are the features I use most often and *highly* recommend.
+
+📖 [Share again](https://pkg.garrickadenbuie.com/xaringanExtra/#/share-again)
+
+
+
+📖 [Panelset](https://pkg.garrickadenbuie.com/xaringanExtra/#/panelset)
+
+
+
+📖 [Tile view](https://pkg.garrickadenbuie.com/xaringanExtra/#/tile-view)
+
+
+
+📖 [Extra styles](https://pkg.garrickadenbuie.com/xaringanExtra/#/extra-styles)
+
+
+
+[Jump back up to see more tools](#tools) ⤴️
+
+{{< /panel >}}
+
+{{< panel name="`flair`" >}}
+
+📦 [r-for-educators.github.io/flair](https://r-for-educators.github.io/flair/index.html)
+
+ [Kelly Bodwin](https://www.kelly-bodwin.com/)
+
+`{flair}` allows you to spice up your code with color-coding and dynamic syntax highlighting. One of the most useful applications is to match colors to concepts -- e.g. giving each argument of a function a unique color. I feel like I've only scratched the surface with `{flair}` and can't wait to use it more in my teaching going forward.
+
+Below is a demonstration of color-coding with `flair` to introduce `dplyr::filter()` and its arguments.
+
+
+
+
+
+
+You can read more about other educational use cases for `flair` in this great [post](https://education.rstudio.com/blog/2020/05/flair/) on the RStudio Education Blog.
+
+[Jump back up to see more tools](#tools) ⤴️
+
+{{< /panel >}}
+
+{{< panel name="`flipbookr`" >}}
+
+📦 [evamaerey.github.io/flipbooks/about](https://evamaerey.github.io/flipbooks/about)
+
+ [Gina Reynolds](https://evangelinereynolds.netlify.app/)
+
+`{flipbookr}` is an amazing teaching tool -- it allows you to incrementally build up a plot line by line, which capitalizes on the "blink comparator" method. This means that students are able to easily map a specific change in code to a specific visual change in the corresponding plot output. Flipbooks are also great for demonstrating incremental changes in a data wrangling pipeline, and they're relatively easy to make!
+
+
+
+[Jump back up to see more tools](#tools) ⤴️
+
+{{< /panel >}}
+
+{{< panel name="`countdown`" >}}
+
+📦 [pkg.garrickadenbuie.com/countdown](https://pkg.garrickadenbuie.com/countdown/)
+
+ [Garrick Aden-Buie](https://www.garrickadenbuie.com/)
+
+`{countdown}` is another great gem from Garrick and allows you to put timers directly on your slides. This is really useful for timed "Your Turn" exercises or to make sure you stay on track with Q & A sessions or breaks.
+
+
+
+[Jump back up to see more tools](#tools) ⤴️
+
+{{< /panel >}}
+{{< /panelset >}}
+
+### Resources I recommend
+
+#### Sharing on short notice {#ssn}
+
+ [Alison Hill](https://alison.rbind.io/), [Desirée De Leon](https://desiree.rbind.io/)
+
+A super helpful webinar on how best to share your teaching materials online.
+
+- [webinar](https://rstudio.com/resources/webinars/sharing-on-short-notice-how-to-get-your-materials-online-with-r-markdown/)
+- [slides](https://rstudio-education.github.io/sharing-short-notice/)
+- [share-blogdown template](https://github.com/apreshill/share-blogdown)
+- [blog post](https://education.rstudio.com/blog/2020/04/sharing-on-short-notice/)
+
+#### Teaching online on short notice
+
+ [Greg Wilson](https://third-bit.com/)
+
+Concrete tips and advice on making the most of teaching via a webcam. There's a ton of great stuff in here you wouldn't necessarily think of, including important advice on making your teaching accessible and inclusive in an online format.
+
+- [webinar](https://rstudio.com/resources/webinars/teaching-online-at-short-notice/)
+- [slides](https://docs.google.com/presentation/d/1rE5e2kSFNICNkBJ4iIIgd9eqACi62gxahknKLtw9Hzs/edit#slide=id.g55ddde1eae_0_2)
+- [blog post](https://education.rstudio.com/blog/2020/03/teaching-online-on-short-notice/)
+
+#### Teaching R online with RStudio Cloud
+
+ [Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
+
+A very thorough and easy to follow walk-through of using RStudio Cloud for teaching, highlighting its most useful features.
+
+- [webinar](https://rstudio.com/resources/webinars/teaching-r-online-with-rstudio-cloud/)
+- [slides](https://mine-cetinkaya-rundel.github.io/rstudio-cloud-webinar/rstudio-cloud.html#1)
+- [blog post](https://education.rstudio.com/blog/2020/04/teaching-with-rstudio-cloud-q-a/)
+
+#### Teaching the tidyverse in 2020
+
+ [Mine Çetinkaya-Rundel](https://www2.stat.duke.edu/~mc301/)
+
+A series of blog posts describing a recommended order in which to teach tidyverse topics to beginners, including very recent tidyverse features that are useful for R users at all levels to learn
+
+- [Part 1: Getting started](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-1-getting-started/)
+- [Part 2: Data visualization](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-2-data-visualisation/)
+- [Part 3: Data wrangling and tidying](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-3-data-wrangling-and-tidying/)
+- [Part4: Part 4: When to purrr?](https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-4-when-to-purrr/)
+
+#### Data science concept maps
+
+A growing list of concept maps related to data science topics in R. Great for planning your lessons and/or sharing in your slides to summarize topics, no matter how seemingly simple or complex.
+
+ Community contributors, curated by [Greg Wilson](https://third-bit.com/)
+
+- [github repo](https://github.com/rstudio/concept-maps)
+- [google drive folder](https://docs.google.com/presentation/d/1ForBjP0pVhljBLuqOyYfyHw_1rrwJzpWW1ZHzCqAJpU/edit#slide=id.p)
+- [blog post](https://education.rstudio.com/blog/2020/09/concept-maps/)
+
+#### rstats artwork {#artwork}
+
+ [Allison Horst](https://www.allisonhorst.com/)
+
+A collection of mind-blowing art that makes it 1000% more fun to learn R.
+
+- [github repo](https://github.com/allisonhorst/stats-illustrations)
+- [interview with Allison Horst](https://www.dataquest.io/blog/making-learning-to-code-friendlier-with-art-allison-horst-interview/)
+
+### The importance of encouragement & positivity
+
+The leaRning curve is no secret. I hadn't touched R before starting grad school in 2017, but I had heard whispers here and there that learning R is really difficult. But I think there's an element of self-fulfilling prophecy here. If you expect it to be impossible, then it will feel impossible. I more or less started my journey with that expectation.
+
+Things changed for me when I took my first course with [Daniel Anderson](https://twitter.com/datalorax_). Daniel has developed a fantastic 5-course [Data Science Specialization in Educational Leadership](https://education.uoregon.edu/data-science-specialization-educational-leadership) in the [College of Education](https://education.uoregon.edu/) at the University of Oregon, taught entirely in R, which ranges from the very basics of R to advanced machine learning with [tidymodels](https://www.tidymodels.org/) (see more info [here](data_sci_specialization.jpg)). Daniel's teaching completely changed the way I approached using and learning R, and it was largely on his recommendation that I joined #rstats Twitter (which was a game-changer). More importantly, Daniel modeled the kind of teacher I wanted to be -- clear, thorough, thoughtful, and above all else, kind and inclusive of everyone.
+
+It was very much with Daniel's model in mind that I found inspiration for making learning R feel more inviting and less daunting. Here are a few things that came to mind that can be abstracted to some general advice...
+
+#### Anticipate the challenge
+
+Recognize the fact that learning R is *hard*. Don't pretend it's a walk in the park -- it isn't. But at the same time, emphasize that the investment of time it takes is worth it!
+
+
+
+
+
+
+#### Normalize errors & mistakes
+
+The first time someone uses R, error messages are one of the first things that they'll see. As we all know, this feels frustrating, especially as a beginner. So it makes sense to acknowledge that up front and discuss what error messages are and why they occur. As error messages go hand-in-hand with debugging, it's also a good idea to at least introduce that concept as well, without necessarily going into great depth since that's a whole other topic of it's own. As debugging is commonly considered part of ["what they forgot to teach you about R"](https://rstats.wtf/debugging-r-code.html), I'm sure I'm not alone in wishing that I had been introduced to debugging much earlier on in my R learning experience.
+
+While learning a systematic approach to debugging is important down the line, it's more important at first for beginners to understand that seeing lots of error messages at first is not a bad thing. It's worth spending some effort to convince your students that error messages should not be cause for discouragement or giving up. Simply put, error messages are part and parcel of programming. Sometimes they take a matter of seconds to fix, sometimes a matter of weeks, but everyone who uses R will regularly encounter error messages, no matter your level of experience. And when it really comes down to it, every error message is an opportunity to learn something!
+
+
+
+
+
+
+
+
+Taking this one step further, it's a good idea to deliberately incorporate making mistakes into your own teaching and use error messages as a teachable moment. You can even use unintentional mistakes as teachable moments -- demonstrate for your students how you fix the mistake and invite them to give their thoughts and feedback. This not only makes your presentation less rehearsed, but it provides a really valuable "real-world" context for learning.
+
+
+
+
+### Make your materials friendly and inviting!
+
+If your slides read like one long piece of dense help documentation, people are not going to feel inclined to engage with it. How do you make your materials more inviting and approachable?
+
+One of the most powerful tools out there, in my opinion, is the incredible artwork by Allison Horst, RStudio's first [artist-in-residence](https://blog.rstudio.com/2019/11/18/artist-in-residence/) (see more [above](#artwork)). The bigger picture behind the artwork, in Allison's words:
+
+>"All of it is towards a goal of trying to make R, and data science in general, more approachable, welcoming, and engaging to diverse learners".
+
+
+
+### A final thought
+
+No matter how long someone has been using R, it never hurts to remind them (yourself included) that a little time and effort can go a long way.
+
+
";return div.childNodes[1]}function hasLength(input){return input.length>0}function trim(str){return str.replace(/^\s+|\s+$/g,"")}function flatten(input){return[].concat.apply([],input)}function isObject(input){return Object.prototype.toString.call(input)==="[object Object]"}function isArray(input){return Object.prototype.toString.call(input)==="[object Array]"}},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/header-attrs/header-attrs.js b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/header-attrs/header-attrs.js
new file mode 100644
index 0000000..dd57d92
--- /dev/null
+++ b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/header-attrs/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/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/panelset.css b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/panelset.css
new file mode 100644
index 0000000..7436b60
--- /dev/null
+++ b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/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/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/panelset.js b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/panelset.js
new file mode 100644
index 0000000..80e773c
--- /dev/null
+++ b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/index_files/panelset/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/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/monster_support.jpg b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/monster_support.jpg
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/monster_support.jpg
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/monster_support.jpg
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/panelset.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/panelset.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/panelset.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/panelset.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/r_rollercoaster.png b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/r_rollercoaster.png
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/r_rollercoaster.png
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/r_rollercoaster.png
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/share_again.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/share_again.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/share_again.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/share_again.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/tile_view.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/tile_view.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/tile_view.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/tile_view.mov
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/time_effort.gif b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/time_effort.gif
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/time_effort.gif
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/time_effort.gif
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/uopsych_bootcamp_registration_deidentified.csv b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/uopsych_bootcamp_registration_deidentified.csv
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/uopsych_bootcamp_registration_deidentified.csv
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/uopsych_bootcamp_registration_deidentified.csv
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo.mp4 b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo.mp4
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo.mp4
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo.mp4
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo1.mov b/content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo1.mov
similarity index 100%
rename from content/post/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo1.mov
rename to content/blog/2020-10-19-teaching-an-r-bootcamp-remotely/xaringan_demo1.mov
diff --git a/content/blog/_index.md b/content/blog/_index.md
new file mode 100644
index 0000000..68ed5ac
--- /dev/null
+++ b/content/blog/_index.md
@@ -0,0 +1,38 @@
+---
+title: Blog
+description: |
+author: "Brendan Cullen"
+show_post_thumbnail: true
+thumbnail_left: false # for list-sidebar only
+show_author_byline: false
+show_post_date: true
+# for listing page layout
+layout: list # list, list-sidebar, list-grid
+
+# for list-sidebar layout
+sidebar:
+ title: My blog
+ description: |
+ My musings about R.
+
+ Check out the _index.md file in the /blog folder
+ to edit this content.
+ author: "The R Markdown Team @RStudio"
+ text_link_label: Subscribe via RSS
+ text_link_url: /index.xml
+ show_sidebar_adunit: false # show ad container
+
+# set up common front matter for all pages inside blog/
+cascade:
+ author: "Brendan Cullen"
+ show_author_byline: true
+ show_post_date: true
+ show_comments: false # see site config to choose Disqus or Utterances
+ # for single-sidebar layout
+ sidebar:
+ text_link_label: View recent posts
+ text_link_url: /blog/
+ show_sidebar_adunit: false # show ad container
+---
+
+** No content below YAML for the blog _index. This file provides front matter for the listing page layout and sidebar content. It is also a branch bundle, and all settings under `cascade` provide front matter for all pages inside blog/. You may still override any of these by changing them in a page's front matter.**
diff --git a/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.Rmd b/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.Rmd
deleted file mode 100644
index bef0dff..0000000
--- a/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.Rmd
+++ /dev/null
@@ -1,88 +0,0 @@
----
-title: Data Science Training in Psychology
-author: Brendan Cullen
-date: '2020-03-08'
-slug: []
-categories: []
-tags:
- - data science
- - education
- - R
- - grad school
-subtitle: ''
-summary: 'Reflections on the importance of data science training in psychology and how we might close training gaps for grad students.'
-authors: []
-lastmod: '2020-03-08T21:38:45-07:00'
-featured: no
-image:
- caption: 'Photo by Emile Perron on Unsplash'
- focal_point: ''
- preview_only: no
-projects: []
----
-
-Psychology is generally considered a "soft" science, on the opposite end of the spectrum from the "hard" sciences of physics, chemistry, and biology. This often creates a misconception that psychology is somehow not as quantitative, computational, or rigorous, methodologically. To the contrary, psychology is in fact very "hard" (some might even say, ["the hardest"](https://thehardestscience.com/2009/03/14/making-progress-in-the-hardest-science/){target="_blank"}). Why? Because explaining human cognition and behavior is really difficult. People do not think and behave in predictable and consistent ways like atoms and molecules.
-
-Indeed, the combination of random variation ("noise") in how we humans respond to our environment on an given day/hour/minute, combined with the inherent challenge of proper sampling, reliable measurement and accurate model building makes data analysis for a psychologist no easy feat. Explaining variance in psychological data has required centuries of refining statistical methods and computational tools. Fortunately, today's scientists have access to open-source software like R and Python that have *vastly* enhanced our ability to work with data in a way that is more transparent and reproducible. As a result, the teaching of these tools is becoming increasingly more common in psychology graduate programs (and many other fields), particularly in statistics classes.
-
-***
-
-# Graduate statistics
-
-The Department of Psychology at the University of Oregon requires first-year graduate students to take a 3-course series of classes on statistics and data analysis. (You can access the materials for these classes [here.](https://github.com/uopsych){target="_blank"}) As I'm sure used to be the case in psychology departments across many universities, the labs for these classes were originally taught in SPSS. However, thanks to the efforts of some hard-working graduate teaching assistants who served as lab instructors at the time, the labs eventually transitioned to being taught entirely in R.
-
-
-
When I started TA-ing for graduate stats, we (@roseberrymaier, @flourneuro) translated the labs from SPSS to R. We created a bunch of .Rmd files for students to work from. It's so cool to see that those students are the TAs now, and they're creating these amazing materials! https://t.co/myMGefLxQX
-
-
-While learning R in first-year grad stats has immense benefits, it is also really challenging. This was certainly my experience, anyway. In addition to grappling with the dense conceptual material, learning a programming language and using it to do statistics felt really daunting since I had very little programming background before graduate school. And the reality is, given that many (myself included) tend to experience a large learning curve with programming, combined with the already hefty gradstats curriculum, there just isn't space in these classes to teach students much beyond the basics of R.
-
-***
-
-# Training needs
-
-But the way things seem to be moving, it's becoming more common for many students to need more general data science skills in grad school. Current psychology grad students at UO (n = 28) were recently surveyed about the degree to which they perceive they will need different data science-related skills for their desired careers and how much training in those skills is available at UO to their knowledge. Specifically, they were asked,
-
-* On a scale of 0 ("Not at all") to 4 ("Essential"), how much do you NEED this skill for your desired career?
-
-* On a scale of 0 ("Not at all") to 4 ("Complete"), how much training is PROVIDED in this skill at your institution?
-
-
-I created the plot below (using ggplot2) to visualize how much students report they need these skills compared to how much training they feel they already have.
-
-![](training_dotplot_se.png)
-
-Interestingly, the top two skills that students reported needing the most on average for their careers are data visualization and data wrangling. Fortunately, this was the first year (to my knowledge) that PSY611, the first course in the gradstats sequence, included entire labs devoted to [data visualization](https://uopsych.github.io/psy611/labs/lab-6.html){target="_blank"} and [data wrangling](https://uopsych.github.io/psy611/labs/lab-5.html){target="_blank"}. More good news is that other faculty in the psych department are starting to offer courses that focus more on these skills that students seem to need the most. For example, [Rob Chavez](https://twitter.com/robchavez){target="_blank"} has offered a fantastic seminar called [Data Science Methods in Psychology](https://robchavez.github.io/datascience_gallery/syllabus.html){target="_blank"} that covered a wide range of data science topics from [programming in R](https://robchavez.github.io/datascience_gallery/html_only/general_programming.html){target="_blank"} to [text processing](https://robchavez.github.io/datascience_gallery/html_only/text_processing.html){target="_blank"} to [package creation](https://robchavez.github.io/datascience_gallery/html_only/packages.html){target="_blank"} that ultimately turned into a great collection of student-created tutorials (all of which are available [here](https://robchavez.github.io/datascience_gallery/index.html){target="_blank"}).
-
-
-
A collection of fantastic R tutorials from my 'Data Science Methods in Psychology' seminar course, created by our amazing @UOPsych grad students. https://t.co/DhBcn940uz
-
-
-Among other crucial research skills like study design, data collection, and research ethics, the other most coveted technical skill seems to be *programming*. In fact, general programming skills seems to be where there is currently the biggest gap in training in our department. The graph below shows skills ranked in descending order by how large the gap is between how much training in those skills students need and how much they currently have.
-
-![](training_gaps.png)
-
-On the whole, it seems that that there are bigger training gaps for more general data science skills (e.g., programming in R and Python, data wrangling, data visualization). In contrast, the smallest gaps exist for more specialized skills like advanced statistics (e.g., computational modeling, network analysis, structural equation modeling) -- likely because our department has an entire class devoted to each of these topics.
-
-***
-# Learning Resources
-
-So, for the most part, it seems that grad students in our department want more training in general data science skills above and beyond the training they are currently receiving through coursework. Often what this means is that grad students end up teaching themselves (and each other) these skills. Some of my peers have made really incredible tutorials on new tools and methodologies they've recently learned. Sometimes students also attend specialized methods workshops and take really detailed notes that could greatly benefit others who want to learn the same kind of methods. My goal is to make it easier for people (both within our department and beyond) to find these resources.
-
-To that end, I am currently working with [Sara Weston](https://twitter.com/saraweston09){target="_blank"} to create and curate a searchable central repository of data science resources at UO that will house such student-created tutorials, workshop notes, and other data science products (e.g. R packages, shiny apps, etc.) that other students can benefit from. We are also planning to add resources from our department's data science and statistics classes (e.g. the gradstats sequence, multilevel modeling, network analysis, data science seminar, etc.). The hope is that making these resources easier to find and share by putting them all in one place will start to reduce some of the current gaps in data science training. The additional benefit is that students will be able to share their data science "side projects" more broadly, and it will be easier for people to know who they might be able to ask for help with learning certain topics when they need it.
-
->This is a work in progress, so stay tuned for more details!
-
-***
-
-# A final thought
-
-Reflecting on all this has brought home a thought that I think is worth sharing. I have come to realize that, **as grad students, one of the best resources we have access to during our time in grad school is *each other***. Personally, I have learned so much over the years from my [fellow lab members](https://sanlab.uoregon.edu/people/){target="_blank"}. Without them, I would not have conquered my fear of Github or felt inspired to learn more about R and other programming languages. Perhaps the most impactful benefit I've received from them, though, is their *encouragement* -- and that, in particular, is something I hope to pay forward as much as possible.
-
-We all enter grad school with different backgrounds and skill sets, and in so many situations the combination of our different strengths can lead to mutual benefit. So why not help each other out?
-
-
diff --git a/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.html b/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.html
deleted file mode 100644
index 7f2fcb1..0000000
--- a/content/post/2020-03-08-data-science-training-needs-in-grad-school/index.html
+++ /dev/null
@@ -1,89 +0,0 @@
----
-title: Data Science Training in Psychology
-author: Brendan Cullen
-date: '2020-03-08'
-slug: []
-categories: []
-tags:
- - data science
- - education
- - R
- - grad school
-subtitle: ''
-summary: 'Reflections on the importance of data science training in psychology and how we might close training gaps for grad students.'
-authors: []
-lastmod: '2020-03-08T21:38:45-07:00'
-featured: no
-image:
- caption: 'Photo by Emile Perron on Unsplash'
- focal_point: ''
- preview_only: no
-projects: []
----
-
-
-
-
-
-
-
Psychology is generally considered a “soft” science, on the opposite end of the spectrum from the “hard” sciences of physics, chemistry, and biology. This often creates a misconception that psychology is somehow not as quantitative, computational, or rigorous, methodologically. To the contrary, psychology is in fact very “hard” (some might even say, “the hardest”). Why? Because explaining human cognition and behavior is really difficult. People do not think and behave in predictable and consistent ways like atoms and molecules.
-
Indeed, the combination of random variation (“noise”) in how we humans respond to our environment on an given day/hour/minute, combined with the inherent challenge of proper sampling, reliable measurement and accurate model building makes data analysis for a psychologist no easy feat. Explaining variance in psychological data has required centuries of refining statistical methods and computational tools. Fortunately, today’s scientists have access to open-source software like R and Python that have vastly enhanced our ability to work with data in a way that is more transparent and reproducible. As a result, the teaching of these tools is becoming increasingly more common in psychology graduate programs (and many other fields), particularly in statistics classes.
-
-
-
Graduate statistics
-
The Department of Psychology at the University of Oregon requires first-year graduate students to take a 3-course series of classes on statistics and data analysis. (You can access the materials for these classes here.) As I’m sure used to be the case in psychology departments across many universities, the labs for these classes were originally taught in SPSS. However, thanks to the efforts of some hard-working graduate teaching assistants who served as lab instructors at the time, the labs eventually transitioned to being taught entirely in R.
-
-
-
-When I started TA-ing for graduate stats, we (@roseberrymaier, @flourneuro) translated the labs from SPSS to R. We created a bunch of .Rmd files for students to work from. It's so cool to see that those students are the TAs now, and they're creating these amazing materials! https://t.co/myMGefLxQX
-
-While learning R in first-year grad stats has immense benefits, it is also really challenging. This was certainly my experience, anyway. In addition to grappling with the dense conceptual material, learning a programming language and using it to do statistics felt really daunting since I had very little programming background before graduate school. And the reality is, given that many (myself included) tend to experience a large learning curve with programming, combined with the already hefty gradstats curriculum, there just isn’t space in these classes to teach students much beyond the basics of R.
-
-
-
-
Training needs
-
But the way things seem to be moving, it’s becoming more common for many students to need more general data science skills in grad school. Current psychology grad students at UO (n = 28) were recently surveyed about the degree to which they perceive they will need different data science-related skills for their desired careers and how much training in those skills is available at UO to their knowledge. Specifically, they were asked,
-
-
On a scale of 0 (“Not at all”) to 4 (“Essential”), how much do you NEED this skill for your desired career?
-
On a scale of 0 (“Not at all”) to 4 (“Complete”), how much training is PROVIDED in this skill at your institution?
-
-
I created the plot below (using ggplot2) to visualize how much students report they need these skills compared to how much training they feel they already have.
-
-
Interestingly, the top two skills that students reported needing the most on average for their careers are data visualization and data wrangling. Fortunately, this was the first year (to my knowledge) that PSY611, the first course in the gradstats sequence, included entire labs devoted to data visualization and data wrangling. More good news is that other faculty in the psych department are starting to offer courses that focus more on these skills that students seem to need the most. For example, Rob Chavez has offered a fantastic seminar called Data Science Methods in Psychology that covered a wide range of data science topics from programming in R to text processing to package creation that ultimately turned into a great collection of student-created tutorials (all of which are available here).
-
-
-
-A collection of fantastic R tutorials from my ‘Data Science Methods in Psychology’ seminar course, created by our amazing @UOPsych grad students. https://t.co/DhBcn940uz
-
Among other crucial research skills like study design, data collection, and research ethics, the other most coveted technical skill seems to be programming. In fact, general programming skills seems to be where there is currently the biggest gap in training in our department. The graph below shows skills ranked in descending order by how large the gap is between how much training in those skills students need and how much they currently have.
-
-
On the whole, it seems that that there are bigger training gaps for more general data science skills (e.g., programming in R and Python, data wrangling, data visualization). In contrast, the smallest gaps exist for more specialized skills like advanced statistics (e.g., computational modeling, network analysis, structural equation modeling) – likely because our department has an entire class devoted to each of these topics.
-
-
-
-
Learning Resources
-
So, for the most part, it seems that grad students in our department want more training in general data science skills above and beyond the training they are currently receiving through coursework. Often what this means is that grad students end up teaching themselves (and each other) these skills. Some of my peers have made really incredible tutorials on new tools and methodologies they’ve recently learned. Sometimes students also attend specialized methods workshops and take really detailed notes that could greatly benefit others who want to learn the same kind of methods. My goal is to make it easier for people (both within our department and beyond) to find these resources.
-
To that end, I am currently working with Sara Weston to create and curate a searchable central repository of data science resources at UO that will house such student-created tutorials, workshop notes, and other data science products (e.g. R packages, shiny apps, etc.) that other students can benefit from. We are also planning to add resources from our department’s data science and statistics classes (e.g. the gradstats sequence, multilevel modeling, network analysis, data science seminar, etc.). The hope is that making these resources easier to find and share by putting them all in one place will start to reduce some of the current gaps in data science training. The additional benefit is that students will be able to share their data science “side projects” more broadly, and it will be easier for people to know who they might be able to ask for help with learning certain topics when they need it.
-
-
This is a work in progress, so stay tuned for more details!
-
-
-
-
-
A final thought
-
Reflecting on all this has brought home a thought that I think is worth sharing. I have come to realize that, as grad students, one of the best resources we have access to during our time in grad school is each other. Personally, I have learned so much over the years from my fellow lab members. Without them, I would not have conquered my fear of Github or felt inspired to learn more about R and other programming languages. Perhaps the most impactful benefit I’ve received from them, though, is their encouragement – and that, in particular, is something I hope to pay forward as much as possible.
-
We all enter grad school with different backgrounds and skill sets, and in so many situations the combination of our different strengths can lead to mutual benefit. So why not help each other out?
-
-
-
-
diff --git a/content/post/2020-03-08-one-size-rarely-fits-all/index.html b/content/post/2020-03-08-one-size-rarely-fits-all/index.html
deleted file mode 100644
index 7f4fad2..0000000
--- a/content/post/2020-03-08-one-size-rarely-fits-all/index.html
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: One Size Rarely Fits All
-author: Brendan Cullen
-date: '2020-03-08'
-slug: []
-categories:
-tags:
- - precision-medicine
- - health
- - psychology
-subtitle: ''
-summary: 'A case for a precision medicine approach to behavioral health in psychology'
-authors: []
-lastmod: '2020-03-08T16:36:57-07:00'
-featured: no
-image:
- caption: 'Source: Shutterstock / HelloRF Zcool'
- focal_point: ''
- preview_only: FALSE
-projects: []
----
-
-
-
-
-
-
-
Think about the last time you had a splitting headache and needed some quick relief. Which bottle did you reach for? Tylenol or Advil? Why? Maybe you think of yourself as a “Tylenol person” or an “Advil person” because one of these has worked for you before. Or maybe one always upsets your stomach. The point is that not everyone experiences the same pain relief from one pill. Some people prefer Tylenol and others Advil, but nobody quite knows why.
-
The same is true of psychological treatments—they don’t work the same way for all people. People differ in how they respond to treatments for depression, anxiety, addiction, and so forth. The lingo in the field is that there are individual differences in treatment effectiveness. Why? Because, to state the obvious, no two people are exactly alike. And that fact poses a problem for the study of these treatments. Researchers test psychological treatments the same way they test drugs like Tylenol and Advil—using randomized controlled trials (RCTs). People are assigned at random to either one group, which receives a treatment, or another group, which does not. RCTs are an excellent way to assess the differences between the groups on average. The group difference indicates how well the treatment works. The problem is that researchers tend to treat people who differ from their group’s average as mere statistical fluctuations—“noise” in the signal.
-
The drawback of group-to-group comparisons is that they hide person-to-person differences that may be important. For example, even when one group does a lot better than another on average, there may still be many people in the first group who do not improve at all. Or maybe some people in the first group get worse even though their group got better overall. Instead of only thinking at the “group” level, we need to pay more attention to person-to-person differences. This will help us learn why treatments work only for some individuals and not others.
-
How do we learn for whom psychological treatments will work? There are three main things we need to know:
-
-
1) How does the treatment work?
-
At this point, there is strong evidence that Tylenol is an effective painkiller. But, even after decades of research, we still don’t fully understand how Tylenol relieves pain. Similarly, though we know that many psychological treatments are effective (at least for some people), we do not know how these treatments work. For example, researchers don’t know which parts of the brain are changed by most treatments. If we knew more specifics about how a treatment worked, we could improve it. We could focus our efforts on the parts of the treatment that make people better and remove the parts that don’t seem as important. And here’s the bonus: If we knew how treatments worked, that would help us learn for whom they work. Imagine we knew that a treatment reduced depression by decreasing self-criticism. In other words, a reduction in self-criticism is the one and only active ingredient in this treatment. If so, then people who criticize themselves a lot would be good candidates to benefit most from this treatment.
-
-
-
2) What are the unique causes of the problem for a given person?
-
To predict whether someone would benefit from a given treatment, we need to know more about the special factors underlying that person’s problem. In terms of pain, Tylenol is usually the better option for headache pain, and Advil is a good bet for inflammation. Similarly, a psychological treatment will work for a given person only if it addresses whatever caused the problem in the first place. Consider two people who both experience severe anxiety, but for different reasons. If genetic factors cause one person’s anxiety while past trauma is the main source of the other person’s anxiety, then these two individuals will likely need different types of treatment.
-
-
-
3) How does the treatment mesh with a person’s unique characteristics?
-
Like all drugs, Tylenol and Advil have side effects. And it turns out that they have different side effects depending on whether somebody is at risk for heart disease. So, people who have experienced a heart attack, for example, must carefully choose which pill to take when they have a headache. Similarly, whether or not a psychological treatment will work for somebody might depend on that person’s age, gender, or life history, to name just a few examples. The success of many treatments also depends on how severe a person’s problem is to begin with. Consider again the example of a treatment for depression that works on average for a group of people. Perhaps this treatment works best for people who are severely depressed because it focuses on a symptom that is more common in those people. A different treatment, which also works on average, might consistently decrease depression in mildly depressed people but not work at all for severely depressed people.
-
-
-
The bottom line
-
With answers to these three questions, researchers can begin to tailor psychological treatments to the unique needs of different people. We know that a given treatment will not work, at least not equally well, for every person. But being able to predict at the outset who will benefit and who won’t could save a lot of time and money. Rather than treating individual differences as “noise,” we can use them to glean potentially important information. If we can better understand why some people benefit from treatment while others don’t, we can make treatments more effective for more people. Eventually, this will allow more people to live healthier lives.
-
-
Note. I originally wrote this piece for Psychology Today. See the original post here.
-
-
diff --git a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.html b/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.html
deleted file mode 100644
index d22bd6b..0000000
--- a/content/post/2020-06-02-tidymodels-decision-tree-learning-in-r/index.html
+++ /dev/null
@@ -1,1212 +0,0 @@
----
-title: 'Tidymodels: Decision Tree Learning in R'
-author: Cianna Bedford-Petersen, Christopher Loan & Brendan Cullen
-date: '2020-06-02'
-slug: []
-categories: []
-tags: []
-subtitle: 'Cianna Bedford-Petersen, Christopher Loan & Brendan Cullen'
-summary: 'An overview and worked example of tree-based machine learning methods in R using `tidymodels`'
-authors: []
-lastmod: '2020-06-02T10:57:23-07:00'
-featured: no
-image:
- caption: 'Image by Ilona Ilyés from Pixabay'
- focal_point: ''
- preview_only: FALSE
-projects: []
-disable_codefolding: false
-codefolding_show: "show"
-codefolding_nobutton: false
----
-
-
-
-
-
-
-
RStudio has recently released a cohesive suite of packages for modelling and machine learning, called {tidymodels}. The successor to Max Kuhn’s {caret} package, {tidymodels} allows for a tidy approach to your data from start to finish. We’re going to walk through the basics for getting off the ground with {tidymodels} and demonstrate its application to three different tree-based methods for predicting student test scores. For further information about the package, you can visit https://www.tidymodels.org/.
-
-
Setup
-
Load both the {tidyverse} and {tidymodels} packages into your environment. We’ll also load in the {skimr} package to help us with some descriptives for our data and a host of other packages that will be required to run our machine learning models.
-
library(tidymodels)
-library(tidyverse) # manipulating data
-library(skimr) # data visualization
-library(baguette) # bagged trees
-library(future) # parallel processing & decrease computation time
-library(xgboost) # boosted trees
-
-
-
Import the data
-
We use simulated data which approximates reading and math scores for ~189,000 3rd-8th grade students in Oregon public schools see this Kaggle page for details. For the purpose of demonstration, we’ll be sampling 1% of the data with sample_frac() to keep computer processing time manageable. All school IDs in the data are real, so we can use that information to link the data with other sources. Specifically, we’re also going to pull in some data on student enrollment in free and reduced lunch from the National Center for Education Statistics and some ethnicity data from the Oregon Department of Education.
-
set.seed(100)
-
-# import data and perform initial cleaning
-# initial cleaning steps include:
-# *recode NA's for lang_cd and ayp_lep to more meaningful values
-# *remove vars with entirely missing data
-# Note: the data is called 'train.csv', but we will actually further split this into its own training and testing data
-
-dat <- read_csv(here::here("static", "data", "train.csv")) %>%
- select(-classification) %>% # remove this variable because it's redundant with `score`
- mutate(lang_cd = ifelse(is.na(lang_cd), "E", lang_cd),
- ayp_lep = ifelse(is.na(ayp_lep), "G", ayp_lep)) %>%
- sample_frac(.01) %>% # sample 1% of the data to reduce run time
- janitor::remove_empty(c("rows", "cols")) %>%
- drop_na() %>%
- select_if(~length(unique(.x)) > 1)
-
-# import fall membership report ethcnicity data and do some basic cleaning and renaming
-sheets <- readxl::excel_sheets(here::here("static", "data", "fallmembershipreport_20192020.xlsx"))
-
-ode_schools <- readxl::read_xlsx(here::here("static", "data", "fallmembershipreport_20192020.xlsx"),
- sheet = sheets[4])
-
-ethnicities <- ode_schools %>%
- select(attnd_schl_inst_id = `Attending School ID`,
- attnd_dist_inst_id = `Attending District Institution ID`,
- sch_name = `School Name`,
- contains("%")) %>%
- janitor::clean_names()
-
-names(ethnicities) <- gsub("x2019_20_percent", "p", names(ethnicities))
-
-# join ethnicity data with original dataset
-dat <- left_join(dat, ethnicities)
-
-# import and tidy free and reduced lunch data
-frl <- rio::import("https://nces.ed.gov/ccd/Data/zip/ccd_sch_033_1718_l_1a_083118.zip",
- setclass = "tbl_df") %>%
- janitor::clean_names() %>%
- filter(st == "OR") %>%
- select(ncessch, lunch_program, student_count) %>%
- mutate(student_count = replace_na(student_count, 0)) %>%
- pivot_wider(names_from = lunch_program,
- values_from = student_count) %>%
- janitor::clean_names() %>%
- mutate(ncessch = as.double(ncessch))
-
-# import student counts for each school across grades
-stu_counts <- rio::import("https://github.com/datalorax/ach-gap-variability/raw/master/data/achievement-gaps-geocoded.csv", setclass = "tbl_df") %>%
- filter(state == "OR" & year == 1718) %>%
- count(ncessch, wt = n) %>%
- mutate(ncessch = as.double(ncessch))
-
-# join frl and stu_counts data
-frl <- left_join(frl, stu_counts)
-
-# add frl data to train data
-dat <- left_join(dat, frl)
-
After loading in our three datasets, we’ll join them together to make one cohesive data set to use for modelling. After joining, the data contains both student-level variables (e.g. gender, ethnicity, enrollment in special education/talented and gifted programs, etc.) and district-level variables (e.g. school longitude and latitude, proportion of students who qualify for free and reduced-price lunch, etc.), all of which will be included for each 3 of our {tidymodels} tree-based examples.
-
For a more complete description of the variables, you can download the data dictionary here.
-
-
-
Explore the data
-
We’ll use the skim() function from {skimr} to take a closer look at our variables. Many numeric predictors are clearly non-normal (see histograms below), but this is no problem as tree-based methods are robust to non-normality.
-
dat %>%
- select(-contains("id"), -ncessch, -missing, -not_applicable) %>% # remove ID and irrelevant variables
- mutate(tst_dt = lubridate::as_date(lubridate::mdy_hms(tst_dt))) %>% # covert test date to date
- modify_if(is.character, as.factor) %>% # convert character vars to factors
- skim() %>%
- select(-starts_with("numeric.p")) # remove quartiles
-
-
Table 1: Data summary
-
-
-
Name
-
Piped data
-
-
-
Number of rows
-
1857
-
-
-
Number of columns
-
41
-
-
-
_______________________
-
-
-
-
Column type frequency:
-
-
-
-
Date
-
1
-
-
-
factor
-
25
-
-
-
numeric
-
15
-
-
-
________________________
-
-
-
-
Group variables
-
None
-
-
-
-
Variable type: Date
-
-
-
-
skim_variable
-
n_missing
-
complete_rate
-
min
-
max
-
median
-
n_unique
-
-
-
-
-
tst_dt
-
0
-
1
-
2018-03-16
-
2018-06-07
-
2018-05-18
-
47
-
-
-
-
Variable type: factor
-
-
-
-
skim_variable
-
n_missing
-
complete_rate
-
ordered
-
n_unique
-
top_counts
-
-
-
-
-
gndr
-
0
-
1
-
FALSE
-
2
-
M: 939, F: 918
-
-
-
ethnic_cd
-
0
-
1
-
FALSE
-
7
-
W: 1151, H: 458, M: 100, A: 79
-
-
-
tst_bnch
-
0
-
1
-
FALSE
-
6
-
G6: 343, 1B: 330, G4: 304, G7: 304
-
-
-
migrant_ed_fg
-
0
-
1
-
FALSE
-
2
-
N: 1793, Y: 64
-
-
-
ind_ed_fg
-
0
-
1
-
FALSE
-
2
-
N: 1842, Y: 15
-
-
-
sp_ed_fg
-
0
-
1
-
FALSE
-
2
-
N: 1614, Y: 243
-
-
-
tag_ed_fg
-
0
-
1
-
FALSE
-
2
-
N: 1759, Y: 98
-
-
-
econ_dsvntg
-
0
-
1
-
FALSE
-
2
-
Y: 1100, N: 757
-
-
-
ayp_lep
-
0
-
1
-
FALSE
-
10
-
G: 1471, F: 164, Y: 72, E: 58
-
-
-
stay_in_dist
-
0
-
1
-
FALSE
-
2
-
Y: 1811, N: 46
-
-
-
stay_in_schl
-
0
-
1
-
FALSE
-
2
-
Y: 1803, N: 54
-
-
-
dist_sped
-
0
-
1
-
FALSE
-
2
-
N: 1846, Y: 11
-
-
-
trgt_assist_fg
-
0
-
1
-
FALSE
-
3
-
N: 1773, Y: 83, y: 1
-
-
-
ayp_schl_partic
-
0
-
1
-
FALSE
-
2
-
Y: 1846, N: 11
-
-
-
ayp_dist_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1803, N: 54
-
-
-
ayp_schl_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1785, N: 72
-
-
-
rc_schl_partic
-
0
-
1
-
FALSE
-
2
-
Y: 1846, N: 11
-
-
-
rc_dist_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1803, N: 54
-
-
-
rc_schl_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1785, N: 72
-
-
-
lang_cd
-
0
-
1
-
FALSE
-
2
-
E: 1815, S: 42
-
-
-
tst_atmpt_fg
-
0
-
1
-
FALSE
-
2
-
Y: 1853, P: 4
-
-
-
grp_rpt_schl_partic
-
0
-
1
-
FALSE
-
2
-
Y: 1846, N: 11
-
-
-
grp_rpt_dist_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1845, N: 12
-
-
-
grp_rpt_schl_prfrm
-
0
-
1
-
FALSE
-
2
-
Y: 1834, N: 23
-
-
-
sch_name
-
1
-
1
-
FALSE
-
699
-
Hig: 14, Jud: 14, Hou: 13, Fiv: 11
-
-
-
-
Variable type: numeric
-
-
-
-
skim_variable
-
n_missing
-
complete_rate
-
mean
-
sd
-
hist
-
-
-
-
-
enrl_grd
-
0
-
1
-
5.44
-
1.69
-
▇▃▅▃▃
-
-
-
score
-
0
-
1
-
2495.34
-
115.19
-
▁▁▂▇▁
-
-
-
lat
-
0
-
1
-
44.79
-
0.99
-
▂▁▂▅▇
-
-
-
lon
-
0
-
1
-
-122.51
-
1.16
-
▅▇▁▁▁
-
-
-
p_american_indian_alaska_native
-
1
-
1
-
0.01
-
0.06
-
▇▁▁▁▁
-
-
-
p_asian
-
1
-
1
-
0.04
-
0.07
-
▇▁▁▁▁
-
-
-
p_native_hawaiian_pacific_islander
-
1
-
1
-
0.01
-
0.01
-
▇▁▁▁▁
-
-
-
p_black_african_american
-
1
-
1
-
0.02
-
0.04
-
▇▁▁▁▁
-
-
-
p_hispanic_latino
-
1
-
1
-
0.25
-
0.18
-
▇▅▂▁▁
-
-
-
p_white
-
1
-
1
-
0.60
-
0.20
-
▁▃▅▇▅
-
-
-
p_multiracial
-
1
-
1
-
0.06
-
0.03
-
▇▆▁▁▁
-
-
-
free_lunch_qualified
-
0
-
1
-
231.23
-
147.55
-
▇▇▃▁▁
-
-
-
reduced_price_lunch_qualified
-
0
-
1
-
39.86
-
24.77
-
▆▇▃▁▁
-
-
-
no_category_codes
-
0
-
1
-
271.09
-
165.44
-
▆▇▃▁▁
-
-
-
n
-
0
-
1
-
816.07
-
536.55
-
▇▃▂▁▁
-
-
-
-
While most of our predictors are categorical, we can use {corrplot} to better visualize the relationships among the numeric variables.
The first step of our analysis is to split our data into two separate sets: a “training” set and a “testing” set. The training set is used to train a model and, if desired, to adjust (i.e., “tune”) the model’s hyperparameters before evaluating its final performance on our test data. By allowing us to test a model on a new sample, we assess “out of sample” accuracy (i.e., unseen data-—what all predictive models are interested in) and limit overfitting to the training set. We can do this efficiently with the initial_split() function. This comes from the {rsample} package, which is part of the {tidymodels} package that we already loaded. Defaults put 75% of the data in the training set and 25% in the test set, but this can be adjusted with the prop argument. Then, we’ll extract the training data from our split object and assign it a name.
-
To further prevent over-fitting, we’ll resample our data using vfold_cv(). This function outputs k-fold cross-validated versions of our training data, where k = the number of times we resample (unsure why v- is used instead of k- here). By using k = 10 data sets, we get a better estimate of the model’s out-of-sample accuracy. On top of decreasing bias from over-fitting, this is essential when tuning hyperparameters (though we plan to apply defaults and not tune here, for brevity). Though our use of 10-fold cross validation is both frequently used and effective, it should be noted that other methods (e.g., bootstrap resampling) or other k-values are sometimes used to accomplish the same goal.
-
# split the data
-split <- initial_split(dat)
-
-# extract the training data
-train <- training(split)
-
-# resample the data with 10-fold cross-validation (10-fold by default)
-cv <- vfold_cv(train)
-
-
-
Pre-processing
-
Before we add in our data to the model, we’re going to set up an object that pre-processes our data. This is called a recipe. To create a recipe, you’ll first specify a formula for your model, indicating which variable is your outcome and which are your predictors. Using ~. here will indicate that we want to use all variables other than score as predictors. Then, we can specify a series of pre-processing steps for our data that directs our recipe to assign our variables a role or performs feature engineering steps. Pre-processing may be sound uncommon, but if you’ve ever used lm() (or several other R functions) you’ve done some of this by simply calling the function (e.g., automatic dummy-coding to handle categorical data). This is beneficial because it gives the analyst more control, despite adding complexity to the process.
rec <- recipe(score ~ ., train) %>%
- step_mutate(tst_dt = as.numeric(lubridate::mdy_hms(tst_dt))) %>% # convert `test date` variable to a date
- update_role(contains("id"), ncessch, new_role = "id vars") %>% # declare ID variables
- step_nzv(all_predictors(), freq_cut = 0, unique_cut = 0) %>% # remove variables with zero variances
- step_novel(all_nominal()) %>% # prepares test data to handle previously unseen factor levels
- step_unknown(all_nominal()) %>% # categorizes missing categorical data (NA's) as `unknown`
- step_medianimpute(all_numeric(), -all_outcomes(), -has_role("id vars")) %>% # replaces missing numeric observations with the median
- step_dummy(all_nominal(), -has_role("id vars")) # dummy codes categorical variables
-
-
-
Create a model
-
The last step before bringing in our data is to specify our model. This will call upon functions from the {parsnip} package, which standardizes language for specifying a multitude of statistical models. There are a few core elements that you will need to specify for each model
-
-
The type of model
-
This indicates what type of model you choose to fit, each of which will be a different function. We’ll be focusing on decision tree methods using bag_tree(), random_forest(), and boost_tree(). A full list of models can be found here https://www.tidymodels.org/find/parsnip/
-
-
-
The engine
-
set_engine() calls the package to support the model you specified above.
-
-
-
The mode
-
set_mode() indicates the type of prediction you’d like to use in your model, you’ll choose between regression and classification. Since we are looking to predict student scores, which is a continuous predictor, we’ll be choosing regression.
-
-
-
The arguments
-
set_args() allows you to set values for various parameters for your model, each model type will have a specific set of parameters that can be altered. For these parameters, you can either set a particular value or you can use the tune function to search for the optimal value of each parameter. Tuning requires a few extra steps, so we will leave the default arguments for clarity. For more information on tuning check out https://tune.tidymodels.org/.
-
-
-
-
Create a workflow
-
Up to this point we’ve been setting up a lot of individual elements and now it is time to combine them to create a cohesive framework, called a workflow, so we can run our desired models. First, we’ll use the workflow() command and then we’ll pulling the recipe and model we already created. The next section shows three examples of specifying models and creating a workflow for different decision tree methods.
-
-
-
Model Examples
-
-
Bagged trees
-
A bagged tree approach creates multiple subsets of data from the training set which are randomly chosen with replacement. Each subset of data is used to train a given decision tree. In the end, we have an ensemble of different models. The predictions from all the different trees are averaged together, giving us a stronger prediction than one tree could independently.
The plot below shows the root nodes from a bagged tree made of 100 trees (10 folds x 10 bootstrapped resamples). Root nodes are the 1st node in a decision tree, and they are determined by which variable best optimizes a loss function (e.g., minimizes mean square error [MSE] for continuous outcomes or Gini Index for categorical outcomes). Put roughly, the most common root nodes can be thought of as the most “important” predictors.
Random forest is similar to bagged tree methodology but goes one step further. In addition to taking random subsets of data, the model also draws a random selection of features. Instead of utilizing all features, the random subset of features allows more predictors to be eligible root nodes. This is particularly useful for handling high dimensionality data (e.g., have more variables than participants/cases).
Boosted trees, like bagged trees, are an ensemble model. Instead of applying successive models to resampled data and pooling estimates, boosted trees fit the next tree to the residuals (i.e., error term) of the prior tree. The goal is to minimize residual error through multiple trees, and is typically done with fairly “shallow” decision tree (i.e., 1-6 splits in each tree). Though each model is only slightly improving the error rate, the sequential use of many shallow trees makes computationally efficient (i.e. reduced run time) and highly accurate predictions.
One of the few downfalls of {tidymodels} is its (current) inability to plot these tree-based models. For the past two models, it was simpler to extract root nodes and plot them, but their interpretation (as we’re fitting to residuals instead of data sets) are not straightforward. For that reason, we don’t have any pretty plots here. Instead, we’ll skip to evaluating the metrics of all models.
-
-
-
-
-
Evaluate metrics
-
After running these three models, it’s time to evaluate their performance. We can do this with tune::collect_metrics(). The table below shows the estimate of the out-of-sample performance for each of our 3 models.
Here, we are faced with a common problem in the machine learning world: choosing between models that perform similarly (see overlapping standard errors). Whether we would prefer random forests or bagged trees may depend on computational efficiency (i.e., time) or other factors. In practice, tuning several hyperparameters may have made one model clearly preferable over the others, but in our case - relying on all defaults - we would probably have similar performance with both models on a new data set and would prefer random forest or boosted tree models for their efficiency.
-
-
-
Out-of-sample performance
-
The final step is to apply each trained model to our test data using last_fit().
The table below shows the actual out-of-sample performance for each of our 3 models.
-
# show performance on test data
-collect_metrics(final_fit_bag) %>%
- bind_rows(collect_metrics(final_fit_rf)) %>%
- bind_rows(collect_metrics(final_fit_boost)) %>%
- filter(.metric == "rmse") %>%
- mutate(model = c("bag", "rf", "boost")) %>%
- select(model, everything()) %>%
- knitr::kable()
-
-
-
-
model
-
.metric
-
.estimator
-
.estimate
-
-
-
-
-
bag
-
rmse
-
standard
-
93.36504
-
-
-
rf
-
rmse
-
standard
-
91.18114
-
-
-
boost
-
rmse
-
standard
-
94.22609
-
-
-
-
After applying our 3 trained models to the unseen test data, it looks like random forest is the winner since it has the lowest RMSE. In this example, we only used 1% of the data to train these models, which could make it difficult to meaningfully compare their performance. However, the random forest model also results in the best out-of-sample prediction (RMSE = 83.47) when using all of the available data, which we did for the Kaggle competition.
A while back I wrote about how we need more data science training as grad students in psychology and that one of the best ways for us to get this training is to learn from each other. This is just one of many reasons why I’m so humbled and excited to have recently become an RStudio Certified Instructor in the tidyverse.
-
I’m looking forward to start implementing and sharing what I learned with my fellow grad students, especially at the end of this month when I will be leading an introductory R workshop for the new cohort of first year PhD and master’s students in my department.
-
As a small way of paying it forward, I wanted to offer a reflection on what I think makes this training so unique and worthwhile along with a summary of what’s involved and some resources for those who might be interested in knowing more.
-
-
-
The what
-
-
The best place the start is to read about the RStudio Instructor Training and Certification Program here. The RStudio Education Blog also has lots of helpful posts about the program.
-
-
The process boils down to three steps.
-
-
Training Course
-
The first step is to sign up for the training course, which will likely be held over Zoom and chunked into 3-4 hour segments across 2-3 days. You can access the training materials here.
The technical exam assesses your proficiency in whatever topic for which you are attempting to become a certified instructor. Currently there are options to become a certified instructor in tidyverse and shiny, and each has its own accompanying technical exam.
-
I took the tidyverse exam, which, broadly speaking, consists of a series of live coding challenges related to using core tidyverse packages for data cleaning and wrangling, data visualization, string manipulation, functional programming, basic statistical modeling, and creating reproducible documents with R Markdown.
-
As many others have suggested, a great way to prepare for this exam is to work through the exercises R for Data Science, particularly for topics that feel rusty to you, and review the community-contributed solutions.
-
-
I highly recommend going through these sample exams from the RStudio Education Blog start to finish to get a sense of what you might need to review.
The first certification exam assesses pedagogical skills related to teaching data science with R and requires giving a 15-minute demonstration lesson on a topic of your choice followed by a series of applied questions, which will likely involve creating formative assessments on unseen material (e.g. multiple choice questions and fill-in-the-blank coding exercises), developing concept maps on data science topics and giving feedback on example teaching based on pedagogical theory.
If you’d like to see an example of a demonstration lesson, below are the materials I created for this portion of the teaching exam. I used penguins from the {palmerpenguins} package as an example data set. (why? because penguins 🐧 🐧 🐧).
-
-
You can find all of the materials for this lesson and the accompanying code on Github. Feel free to share, adapt and re-use for your own teaching.
-
-
-
Slides
-
I made heavy use of Yihui Xie’s {xaringan} 📦, Garrick Aden-Buie’s {xaringanExtra} 📦, and Kelly Bodwin’s {flair} 📦, along with Allison Horst’s unbeatable artwork. For an excellent {xaringan} tutorial, I recommend you check out these slides, from the R Markdown whisperer herself, Alison Hill. Note: you absolutely do not have to use {xaringan} to make your slides, and if your lesson includes more images than code, another method for delivering your slides might be better.
For other community-contributed data science concept maps you can use in your teaching and/or lesson prep, see here.
-
-
❖ ❖ ❖
-
-
-
-
Learner Persona
-
-
For a list of other example learner personas, see here.
-
-
❖ ❖ ❖
-
-
-
-
Formative Assessment
-
I created these interactive exercises using the learnr package, which I highly recommend you check out. It’s quite powerful and versatile.
-
Here’s a quick look.
-
-
-
-
-
-
-
-
The why
-
Ok, this might all seem like quite a bit of time and effort. Why go to the trouble of doing this training? In a word, Greg Wilson.
-
Greg, who co-founded the Software Carpentry, has over 35 years of experience in education in data science and software engineering, and it shows. He is now part of the RStudio Education team, where he runs the the instructor training and certification program. One of the reasons this program stands out is that it benefits from Greg’s unique expertise and careful curation of decades of research on evidence-based teaching methods that he has translated into clear and actionable advice. I can guarantee that you will learn a LOT from him.
Now, here are some other reasons why you should do this training…
-
-
Surge in online teaching
-
Interest in data science education seems to be ever-increasing. The fact that COVID-19 has forced most education to go online might actually present an opportunity to meet this demand in a more scalable and (hopefully more accessible way that doesn’t incur the traditional limitations of travel costs or room capacity. Of course, online education comes with a host of inherent challenges. The training course includes a whole section on this. I also recommend you check out this RStudio webinar and accompanying blog post along with answers to some frequently asked questions about teaching online.
-
As online data science education is becoming increasingly the norm, it seems natural to assume that there will be a need for more certified instructors to meet the growing demand.
-
-
❖ ❖ ❖
-
-
-
-
Teaching resources galore
-
Another great reason to become a certified instructor is that, as a data science educator, you have a huge and ever-increasing bank of resources at your disposal. What’s more, as a certified instructor, you are eligible for free licenses to RStudio Pro products and a significant discount for RStudio Cloud. Here are just some of the great teaching tools from RStudio and the #rstats community.
-
-
The RStudio Education Blog is a 💎 TREASURE TROVE 💎 of resources. Add it to your bookmarks immediately.
The instructor training program started back in February 2019 and as of August 2020 there are almost 150 certified tidyverse instructors and 20 shiny instructors. This means that the program has gone through multiple iterations and has made data-driven improvements based on feedback from participants – especially in the realm of supporting online teaching in the aftermath of COVID-19. So you can rest assured that, while it is still a relatively new program, all the kinks have been worked out.
-
Plus, I’m sure that the content and structure of the training will continue to adapt to the needs and priorities of the community, and you might even be lucky enough to catch a special guest presentation. For example…
-
-
-
-
Enjoyed sharing some tips today on “Teaching in Production” for our [@RStudioEDU] certified-instructors-to-be (another [@thomas_mock] distill success story!)
The focus of this training is not technical competency – it’s how be an effective teacher. One of the most critical components of teaching effectively is to be inclusive of all learners, regardless of race, religion, sexual orientation, gender identity, disability, etc.
-
The #rstats learning community is known for being welcoming and inclusive, so it’s no surprise that the training course emphasizes these values as well. What I appreciate most about this aspect of the training is that it will challenge you to think about questions and hypothetical scenarios to which there are no easy answers.
-
However, it is extremely important to be pushed out of your comfort zone to consciously and proactively reflect on how you will confront issues such as systemic racism and institutionalized violence against BIPOC communities, sexism and a deeply ingrained culture of sexual harassment. These issues will inevitably arise in one form or another in your classroom or teaching setting, and it’s absolutely necessary that we confront these challenges now more than ever. Check out this slide and this talk on effective allyship when you get a chance.
-
-
For further reading on inclusivity and social justice in data science education, I recommend you read this post by Nicole Thompson Gonzalez and this one by Yim Register. Also check out the amazing work that JooYoung Seo, the first blind RStudio Certified Instructor, has been doing to make data science tools more accessible.
-
-
Another exciting feature is that the training materials are now available in Spanish, courtesy of Laura Acion, and hopefully other languages soon, as interest in the training seems to be growing around the world. A similar ongoing project to check out is glosario, an open source glossary of data science terms translated in multiple languages that can be used for teaching (read more here).
-
-
❖ ❖ ❖
-
-
-
-
Community of practice
-
To extend the idea of including everyone who wants to learn data science, we must be active in building teaching communities that extend beyond just the walls of academic institutions.
“equip everyone, regardless of means, to participate in a global economy that rewards data literacy.”
-
-
A more concrete goal, put forth by Carl Howe, Director of Education at RStudio, is to train the next million R users. In becoming an RStudio certified instructor, you can better position yourself to actively participate in reaching this goal. But it’s worth reflecting on the fact that teaching and learning doesn’t happen in a vacuum – this is where the idea of community comes in. In my opinion, the fact that R users around the world already have a strong sense of community will make it that much easier to welcome new learners into the fold and make it more likely that they themselves will start to train others one day.
-
-
Read more about building a community of practice here.
-
-
-
P.S. If you need yet another reason to do this training, you get a fancy certificate at the end. ✨
-
-
-
-
-
-
Get in touch
-
Please feel free to reach out if you are thinking of participating in the training yourself and want to hear more from someone who’s gone through it recently. I would be glad to chat any time!
-
-
diff --git a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.html b/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.html
deleted file mode 100644
index 88f1b83..0000000
--- a/content/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.html
+++ /dev/null
@@ -1,480 +0,0 @@
----
-title: "Flattening the leaRning curve: Teaching R online during COVID-19"
-author: Brendan Cullen
-date: '2020-10-19'
-slug: []
-categories: []
-tags:
- - data science
- - education
- - R
-subtitle: ''
-summary: 'Lessons learned from my first experience teaching an R bootcamp remotely & a collection of tools and resources I found useful'
-authors: []
-lastmod: '2020-10-19T10:26:32-07:00'
-featured: no
-image:
- caption: 'Photo by Martin Adams on Unsplash'
- focal_point: ''
- preview_only: no
-projects: []
-disable_codefolding: false
-codefolding_show: "hide"
-codefolding_nobutton: false
----
-
-
-
-
-
-
-
-
-
-
At this point, you’re probably familiar with the phrase “flatten the curve” — remember back in March when we were all talking about that? It was part of a critical public health messaging campaign aimed at slowing the spread of COVID-19 to prevent hospitals from becoming overwhelmed beyond their capacity. Based on how things are going, we really should still be talking about that. So allow me to unabashedly steal this catchphrase as a flawed metaphor for teaching and learning R during the era of this pandemic…
-
It’s no secret that R has a significant leaRning curve — and, while it seems that more people than ever are now wanting to learn R, almost everyone is having to do it in an online format of some kind. For those who are used to a traditional in-person classroom environment, having a first introduction to R in an online format might make the leaRning curve even steeper (as I said, a flawed metaphor – the concept of a “steep learning curve” is actually the opposite of what most people think, but we’ll run with it anyway). After recently teaching an introductory R Bootcamp online, I’ve spent a lot of time thinking about strategies to lower the learning threshold and make it easier to conquer any potential fear of learning R – to “flatten the leaRning curve”, as it were.
-
-
For anyone who might be new to teaching R, teaching online, or both, the goal of this post is to share some valuable lessons I learned and resources I used during this online teaching experience. I hope it may be of some benefit for your own teaching.
-
-
-
Background
-
Back in Fall 2018, the Department of Psychology at the University of Oregon started to offer a grad-student-led introductory R Bootcamp the week before the start of the new academic year. The bootcamp consists of three 3-4 hour sessions that take place over the course of a week. The idea behind the bootcamp is to give a first exposure to R to incoming students who have little to no background in it before being launched headfirst into using R to analyze data for their first year project and to complete labs and homework assignments for PSY611, the first in a series of graduate statistics courses taught entirely in R.
-
In addition, as I’ve written about previously, current grad students, along with other members of the psychology department, have expressed a keen interest in developing a stronger foundation in skills such as basic programming, data wrangling, and data visualization. So the bootcamp also serves as an opportunity for existing R users to get a refresher and deeper dive into those topics for those who want it.
-
After spending lot of time thinking about how to improve the data science learning experience for my fellow grad students and having recently become an RStudio Certified Instructor in the tidyverse, it was my great privilege to be able to put all of this into action by leading the 3rd Annual UO Psych Bootcamp this year. 🥳
-
-
-
The challenge
-
However, I found myself facing a rather significant challenge. The R Bootcamp, like many intro R workshops, usually occurs in-person in a large room with a giant projector screen, coffee and snacks, and, most importantly, the ability to run over and look over someone’s shoulder at their computer screen when they need help. Because of COVID-19, I needed to design and deliver a bootcamp for a large group of beginners (many using R for the very first time) entirely over a webcam.
-
Moreover, I assumed that student motivation would be at an all-time low and feelings of anxiety and uncertainty would be at an all-time high – especially for those about to start their graduate school journey entirely online, very much contrary to plan. There were a lot of horrible things going on in the world in September 2020, which marked 6 months into the COVID-19 pandemic in the U.S. – people’s loved ones were getting sick, the killing of innocent Black lives continued, a bitter presidential race reached full swing – not to mention devastating wildfires that raged all along the west coast. (Of course, while I wish I could actually write about these events in the past tense, all of these problems continue).
-
So, how do you get people excited about learning R amidst all of that? Needless to say, this felt a little daunting 😨. Fortunately, though, there are people out there who are experts in this sort of thing who have graciously shared their resources and advice, and this helped me immensely to run a successful bootcamp.
-
-
-
Who attended?
-
52 people registered for the bootcamp. While the majority of those who attended were incoming first-year psychology grad students, we also had a mix of more advanced grad students, undergrads, research assistants, lab managers, staff data analysts, and faculty members from a variety of departments/centers across the University, including the Departments of Psychology, Linguistics, Economics and the Center for Translational Neuroscience.
-
# import bootcamp registration data
-registration <- read_csv("uopsych_bootcamp_registration_deidentified.csv")
-
-# clean data
-plot_data <- registration %>%
- janitor::clean_names() %>%
- select(position = what_is_your_position_at_uo,
- experience = do_you_have_any_experience_in_r_no_experience_is_required) %>%
- mutate(position = factor(case_when(position %in% c("Undergraduate", "Undergraduate student") ~ "Undergrad Student",
- position %in% c("RA", "Lab Manager", "Data Analyst") ~ "Research Staff",
- TRUE ~ as.character(position))),
- experience = factor(experience, levels = c(
- "I've never heard of it",
- "I've heard of it but have never used it",
- "I've opened it before",
- "I've used it to analyze data",
- "I use it often to analyze data")))
-
-# plot positions at UO
-theme_set(theme_minimal(base_size = 15))
-theme_update(legend.position = "none",
- plot.title.position = "plot",
- panel.grid.minor.y = element_blank())
-
-plot_data %>%
- count(position) %>%
- ggplot(aes(fct_reorder(position, n), n, fill = position)) +
- geom_col() +
- coord_flip() +
- scale_fill_manual(values = get_pal("Kotare")) +
- labs(x = "", y = "Count", title = "Participants' roles at University of Oregon")
-
-
# plot prior experience
-plot_data %>%
- count(experience) %>%
- ggplot(aes(experience, n, fill = experience)) +
- geom_col() +
- coord_flip() +
- scale_fill_manual(values = get_pal("Kaka")) +
- labs(x = "", y = "Count", title = "Participants' prior experience with R")
-
-
-
-
Logistics
-
-
Zoom + Slack = 👌
-
We ran synchronous sessions live over Zoom. However, rather than use the Zoom chat for communicating with each other and asking questions, we used Slack. A few reasons for this:
-
-
this way people could continue to ask questions outside of the live sessions and a permanent and searchable record of questions and answers would be available for posterity
-
The Zoom chat can get easily cluttered and doesn’t easily allow you to make threads, which keep things more organized
-
Slack has better emojis 🤓.
-
-
I was fortunate to have the very knowledgeable and talented Cameron Kay and Cianna Bedford-Petersen as teaching assistants. Cam and Cianna remained on deck throughout the sessions to answer questions on Slack while we went through the material. We also decided that if a student ran into technical issues or felt completely lost, then one of the TA’s would pull them into a breakout room on Zoom to offer one-on-one help.
-
-
-
RStudio Cloud
-
For “Your Turn” exercises, an idea I stole from Alison Hill’s excellent rstudio::conf(2020) workshop, we used RStudio Cloud, a hosted version of the RStudio IDE available in the web browser. We did this to avoid issues with students installing RStudio on their local machines, as troubleshooting technical issues over Zoom in a large group is not something we felt prepared for. Using RStudio Cloud also allowed me to configure specific IDE settings and pre-load specific packages to allow students to initially avoid technical issues. Lastly, sharing a workspace on RStudio Cloud allowed each student to save their own copy of the projects containing the Your Turn exercises, which in turn made it possible for myself or the TA’s to “peek” into a student’s exercises and help them figure out where their errors were coming from. Overall it went really smoothly, and everyone who filled out the feedback survey said they had no issues using it. I highly recommend using this for your teaching, even if it’s in-person.
-
-
-
Blogdown site
-
To make the bootcamp materials more accessible and shareable, I decided to package them into a website, which I created using the blogdown package (see more on this below). Organizing your teaching materials into a website has three clear advantages in my mind:
-
-
A website makes your materials easier to access and more shareable – you send someone a single link they can access on their phone or computer, no need to download anything
-
A website is highly sustainable in the sense that it’s easy for students to bookmark and refer back to over and over, and if you push changes to Github with continuous deployment (e.g. via Netlify), students will always have access to the most updated materials. This avoids having to introduce Github and version control, which is a whole other beast to teach to beginners.
{xaringanExtra} extends the functionality of the already amazing {xaringan} package by Yihuie Xie, and it has become one of my all-time favorite packages. Here are the features I use most often and highly recommend.
In case it still isn’t obvious enough how much I love this package…
-
-
-Ok, {xaringanExtra} continues to blow my freakin' mind 🤯 Here's a quick demo that shows tile view and embed_xaringan() in the context of a #ggplot2 flipbook (h/t @EvaMaeRey). @grrrck, I owe you an absurd amount of beers 🍻 Thank you for all you do for the #rstats community 🙌 pic.twitter.com/ucMCbOvopW
-
{flair} allows you to spice up your code with color-coding and dynamic syntax highlighting. One of the most useful applications is to match colors to concepts – e.g. giving each argument of a function a unique color. I feel like I’ve only scratched the surface with {flair} and can’t wait to use it more in my teaching going forward.
-
Below is a demonstration of color-coding with flair to introduce dplyr::filter() and its arguments.
-
-
-
-
-
You can read more about other educational use cases for flair in this great post on the RStudio Education Blog.
{flipbookr} is an amazing teaching tool – it allows you to incrementally build up a plot line by line, which capitalizes on the “blink comparator” method. This means that students are able to easily map a specific change in code to a specific visual change in the corresponding plot output. Flipbooks are also great for demonstrating incremental changes in a data wrangling pipeline, and they’re relatively easy to make!
{coundown} is another great gem from Garrick and allows you to put timers directly on your slides. This is really useful for timed “Your Turn” exercises or to make sure you stay on track with Q & A sessions or breaks.
Concrete tips and advice on making the most of teaching via a webcam. There’s a ton of great stuff in here you wouldn’t necessarily think of, including important advice on making your teaching accessible and inclusive in an online format.
A series of blog posts describing a recommended order in which to teach tidyverse topics to beginners, including very recent tidyverse features that are useful for R users at all levels to learn
A growing list of concept maps related to data science topics in R. Great for planning your lessons and/or sharing in your slides to summarize topics, no matter how seemingly simple or complex.
The leaRning curve is no secret. I hadn’t touched R before starting grad school in 2017, but I had heard whispers here and there that learning R is really difficult. But I think there’s an element of self-fulfilling prophecy here. If you expect it to be impossible, then it will feel impossible. I more or less started my journey with that expectation.
-
Things changed for me when I took my first course with Daniel Anderson. Daniel has developed a fantastic 5-course Data Science Specialization in Educational Leadership in the College of Education at the University of Oregon, taught entirely in R, which ranges from the very basics of R to advanced machine learning with tidymodels (see more info here). Daniel’s teaching completely changed the way I approached using and learning R, and it was largely on his recommendation that I joined #rstats Twitter (which was a game-changer). More importantly, Daniel modeled the kind of teacher I wanted to be – clear, thorough, thoughtful, and above all else, kind and inclusive of everyone.
-
It was very much with Daniel’s model in mind that I found inspiration for making learning R feel more inviting and less daunting. Here are a few things that came to mind that can be abstracted to some general advice…
-
-
Anticipate the challenge
-
Recognize the fact that learning R is hard. Don’t pretend it’s a walk in the park – it isn’t. But at the same time, emphasize that the investment of time it takes is worth it! And be sure to remind people of that more than once 😉.
-
-
-
-
-
-
-
Normalize errors & mistakes
-
The first time someone uses R, error messages are one of the first things that they’ll see. As we all know, this feels frustrating, especially as a beginner. So it makes sense to acknowledge that up front and discuss what error messages are and why they occur. As error messages go hand-in-hand with debugging, it’s also a good idea to at least introduce that concept as well, without necessarily going into great depth since that’s a whole other topic of it’s own. As debugging is commonly considered part of “what they forgot to teach you about R”, I’m sure I’m not alone in wishing that I had been introduced to debugging much earlier on in my R learning experience.
-
While learning a systematic approach to debugging is important down the line, it’s more important at first for beginners to understand that seeing lots of error messages at first is not a bad thing. It’s worth spending some effort to convince your students that error messages should not be cause for discouragement or giving up. Simply put, error messages are part and parcel of programming. Sometimes they take a matter of seconds to fix, sometimes a matter of weeks, but everyone who uses R will regularly encounter error messages, no matter your level of experience. And when it really comes down to it, every error message is an opportunity to learn something!
-
-
-
-
-
-
Taking this one step further, it’s a good idea to deliberately incorporate making mistakes into your own teaching and use error messages as a teachable moment. You can even use unintentional mistakes as teachable moments – demonstrate for your students how you fix the mistake and invite them to give their thoughts and feedback. This not only makes your presentation less rehearsed, but it provides a really valuable “real-world” context for learning.
-
-
This idea is referred to as “positive error framing” – and if you want to learn more about this topic in depth I recommend you check out this section from the recent article “Ten quick tips for teaching with participatory live coding” (really you should read the whole article – it’s packed full of great advice).
-
-
-
-
Make your materials friendly and inviting!
-
If your slides read like one long piece of dense help documentation, people are not going to feel inclined to engage with it. How do you make your materials more inviting and approachable?
-
One of the most powerful tools out there, in my opinion, is the incredible artwork by Allison Horst, RStudio’s first artist-in-residence (see more above). The bigger picture behind the artwork, in Allison’s words:
-
-
“All of it is towards a goal of trying to make R, and data science in general, more approachable, welcoming, and engaging to diverse learners”.
-
-
-
Cute gifs never hurt either…
-
-
-If you're teaching #rstats with #palmerpenguins at the moment (which you should be because it's a brilliant dataset 🐧), consider sneaking in a lil' motivational penguin, both for yourself and your students. everything is terrible and we all need small joys now more than ever pic.twitter.com/OHeJWIsqFp
-
I was really happy to see that people seemed to appreciate the positive learning atmosphere and, especially because this was only an introductory workshop, that this made them excited to learn more:
-
-
✍️ “I really appreciated the warm welcome/atmosphere the instructors set up- learning a new programming language can be frustrating, especially for a beginner, so I was really appreciative of the continuous encouragement throughout the bootcamp.”
-
-
✍️ “I really enjoyed how supportive and encouraging the facilitators were. I understood learning R was no easy endeavor but hearing about their experiences was encouraging for me. Also, I greatly appreciate all the amazing resources they have compiled for future use. I definitely plan to continue looking into it!”
-
-
✍️ “I appreciated the facilitators’ organization, support, encouragement, and instructional clarity. Thank you for providing this very warm and accessible introduction for an absolute first-time novice! It’s encouraged me to take more steps into learning R.”
-
-
✍️ “I am now in my third year of struggling through R and this was the first presentation of material that really clicked for me. I frequently refer to the dplyr and ggplot presentations in my work and will continue to work my way through these exercises until I am truly fluent in these basics. THANK YOU”
-
-
So we did we flatten the leaRning curve? Only time will tell. But the most gratifying feedback, in my opinion, is that people who attended felt inspired to keep learning and continue riding the R roller coaster. That’s really the best outcome I could have hoped for!
-
-
-
-
A final thought
-
In short, no matter how long someone has been using R, it never hurts to remind them (yourself included) that a little time and effort can go a long way.
diff --git a/content/post/_index.md b/content/post/_index.md
deleted file mode 100644
index e92d4a0..0000000
--- a/content/post/_index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-header:
- caption: ""
- image: ""
-title: Posts
-view: 2
----
-
-
\ No newline at end of file
diff --git a/content/project/_index.md b/content/project/_index.md
new file mode 100644
index 0000000..c7e1d06
--- /dev/null
+++ b/content/project/_index.md
@@ -0,0 +1,35 @@
+---
+title: Projects
+description: ""
+author: ""
+show_post_thumbnail: true
+show_author_byline: false
+show_post_date: false
+# for listing page layout
+layout: list-grid # list, list-sidebar, list-grid
+
+# for list-sidebar layout
+sidebar:
+ title: A Sidebar for Your Projects
+ description: |
+ Projects can be anything!
+ Check out the _index.md file in the /project folder
+ to edit this content.
+ author: "The R Markdown Team @RStudio"
+ text_link_label: ""
+ text_link_url: ""
+ show_sidebar_adunit: false # show ad container
+
+# set up common front matter for all individual pages inside project/
+cascade:
+ show_author_byline: false
+ show_post_date: false
+ show_comments: false # see site config to choose Disqus or Utterances
+ # for single-sidebar layout only
+ sidebar:
+ text_link_label: View all projects
+ text_link_url: /project/
+ show_sidebar_adunit: true # show ad container
+---
+
+** No content for the project index. This file provides front matter for the blog including the layout and boolean options. **
diff --git a/content/project/data-science-specialization/eds_specialization.jpg b/content/project/data-science-specialization/eds_specialization.jpg
new file mode 100644
index 0000000..f9c488c
Binary files /dev/null and b/content/project/data-science-specialization/eds_specialization.jpg differ
diff --git a/content/project/data-science-specialization/featured.png b/content/project/data-science-specialization/featured.png
new file mode 100644
index 0000000..004ceb4
Binary files /dev/null and b/content/project/data-science-specialization/featured.png differ
diff --git a/content/project/data-science-specialization/index.md b/content/project/data-science-specialization/index.md
new file mode 100644
index 0000000..3b3fe60
--- /dev/null
+++ b/content/project/data-science-specialization/index.md
@@ -0,0 +1,48 @@
+---
+title: "Data Science Specialization in Educational Leadership"
+summary: "A 5-course Data Science Specialization in Educational Leadership I completed at the University of Oregon."
+date: 2021-11-11
+author: ""
+draft: false
+tags:
+categories:
+# layout options: single or single-sidebar
+layout: single
+links:
+- icon: info-circle
+ icon_pack: fas
+ name: More info
+ url: https://education.uoregon.edu/specialization-educational-data-science
+- icon: github
+ icon_pack: fab
+ name: Course repos
+ url: https://github.com/uo-datasci-specialization
+---
+
+As part of my graduate training at the University of Oregon, I completed a Data Science Specialization in Educational Leadership, taught by [Daniel Anderson](https://www.datalorax.com/).
+
+Here are a few samples of the projects I worked on:
+
+### Flexdashboard
+
+A flexdashboard that visualizes data from the Big Cities Health Inventory:
+https://brendanhcullen.github.io/data-viz-dashboard/
+
+### Shiny dashboard
+
+A shiny dashboard that visualizes k-means clustering:
+https://kdestasio.shinyapps.io/fpr_final_project/
+
+### R package
+
+An R package for interfacing with data from the Devaluation study in UO SAN Lab:
+https://uosan.github.io/devaluation/
+
+___
+
+
+
+
+
+
+
diff --git a/content/project/data-viz-dashboard/featured.png b/content/project/data-viz-dashboard/featured.png
deleted file mode 100644
index 8b6092d..0000000
Binary files a/content/project/data-viz-dashboard/featured.png and /dev/null differ
diff --git a/content/project/data-viz-dashboard/index.md b/content/project/data-viz-dashboard/index.md
deleted file mode 100644
index 887334f..0000000
--- a/content/project/data-viz-dashboard/index.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-date: "2020-04-24"
-external_link: https://brendanhcullen.github.io/data-viz-dashboard/
-image:
- caption:
- focal_point: Smart
-summary: A flexdashboard that visualizes data from the Big Cities Health Inventory.
-tags:
-- data viz
-- R
-
-title: Data Vizualization Dashboard
----
-
diff --git a/content/project/devaluation/featured.png b/content/project/devaluation/featured.png
index e4f6cd7..0501204 100644
Binary files a/content/project/devaluation/featured.png and b/content/project/devaluation/featured.png differ
diff --git a/content/project/devaluation/index.md b/content/project/devaluation/index.md
index 8b82bc5..30f97bf 100644
--- a/content/project/devaluation/index.md
+++ b/content/project/devaluation/index.md
@@ -11,11 +11,19 @@ links:
icon_pack: fas
name: More info
url: https://ctn.uoregon.edu/projects/healthy-eating-study
-
+- icon: r-project
+ icon_pack: fab
+ name: R package
+ url: https://uosan.github.io/devaluation/
tags:
- neuroscience
- health
- machine learning
---
-This project is a large-scale randomized-control trial that investigates the efficacy and mechanisms of a healthy eating invention. Specifically, the RCT compares a cognitive reappraisal training, in which participants change the way they think about unhealthy food, to a behavioral response training, in which participants modify their physical motor responses to food stimuli to train neural inhibitory control circuits. Currently, I am working on developing a precision medicine analysis pipeline around a series of additional measures that have been added to this parent R01 as part of the National Center for Biotechnology Information’s [ADOPT Project](https://www.nhlbi.nih.gov/science/adopt) (Accumulating Data to Optimally Predict Obesity Treatment). The ADOPT project aims to solve the precision medicine problem for obesity treatment by identifying core measures assessing a range of behavioral, biological, environmental, and psychosocial factors that contribute to obesity. My role in this project is to develop the analytical infrastructure to create and validate composites of low-cost, easily administered individual difference measures that moderate response to the healthy eating interventions in terms of both magnitude and timing.
+
+
+
+
+
+This project is a large-scale randomized-control trial that investigates the efficacy and mechanisms of a healthy eating invention. Specifically, the RCT compares a cognitive reappraisal training, in which participants change the way they think about unhealthy food, to a behavioral response training, in which participants modify their physical motor responses to food stimuli to train neural inhibitory control circuits. I helped co-design the cognitive reappraisal intervention, and created an automated workflow for daily backup of fMRI data via a high performance computing cluster.
\ No newline at end of file
diff --git a/content/project/devaluation/logo.png b/content/project/devaluation/logo.png
new file mode 100644
index 0000000..e4f6cd7
Binary files /dev/null and b/content/project/devaluation/logo.png differ
diff --git a/content/project/first-year-project/featured.png b/content/project/first-year-project/featured.png
index 38eebf3..f88a8d5 100644
Binary files a/content/project/first-year-project/featured.png and b/content/project/first-year-project/featured.png differ
diff --git a/content/project/first-year-project/index.md b/content/project/first-year-project/index.md
index abc64ba..c66c0ec 100644
--- a/content/project/first-year-project/index.md
+++ b/content/project/first-year-project/index.md
@@ -10,11 +10,11 @@ links:
- icon: file-pdf
icon_pack: fas
name: Pre-print
- url: preprint.pdf
+ url: project/first-year-project/preprint.pdf
- icon: image
icon_pack: fas
name: Poster
- url: poster.pdf
+ url: project/first-year-project/poster.pdf
- icon: link
icon_pack: fa
name: Pre-registration
@@ -25,7 +25,6 @@ tags:
- health
- R
---
+![](pattern_expression.png)
Health-risking behaviors (HRBs), e.g., excessive consumption of alcohol, tobacco, drugs and energy-dense food, contribute to long-term health problems, particularly among individuals who experienced early life adversity (EA). Though traditional executive control tasks are commonly assumed to be relevant for predicting real-world HRBs, recent work has called into question the ecological and predictive validity of these tasks. This study explores the predictive validity of cognitive and affective neural measures derived from a more passive cue reactivity task in a community sample of adults with self-control problems and a history of early adversity. We extracted trial-level estimates of whole-brain expression of canonical “inhibitory control” and “craving” patterns while participants viewed images of personally relevant health-risking substances during the cue reactivity task. Statistical modeling showed that greater trial-level expression of the “craving” and “inhibitory control” patterns predicted higher and lower desire ratings, respectively, for cue reactivity stimuli. However, only “craving” pattern expression predicted measures of real-world craving in daily life. Taken together, these results suggest that, among individuals with self-control problems, the real-world predictive validity of passive neural measures of affective processes may be superior to that of neural measures of executive control.
-
->For more details, see the [pre-print](preprint.pdf) and [poster](poster.pdf).
\ No newline at end of file
diff --git a/content/project/first-year-project/pattern_expression.png b/content/project/first-year-project/pattern_expression.png
new file mode 100644
index 0000000..0d360d2
Binary files /dev/null and b/content/project/first-year-project/pattern_expression.png differ
diff --git a/content/project/k-means-clustering-dashboard/featured.png b/content/project/k-means-clustering-dashboard/featured.png
deleted file mode 100644
index 183d0f9..0000000
Binary files a/content/project/k-means-clustering-dashboard/featured.png and /dev/null differ
diff --git a/content/project/k-means-clustering-dashboard/index.md b/content/project/k-means-clustering-dashboard/index.md
deleted file mode 100644
index df6e883..0000000
--- a/content/project/k-means-clustering-dashboard/index.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-date: "2020-03-26"
-external_link: https://kdestasio.shinyapps.io/fpr_final_project/
-image:
- caption:
- focal_point: Smart
-summary: A shiny dashboard that visualizes k-means clustering
-tags:
-- data viz
-- R
-
-title: K-means Clustering Shiny Dashboard
----
-
diff --git a/content/project/personality-diabetes/featured.jpg b/content/project/personality-diabetes/featured.jpg
deleted file mode 100644
index 7a61723..0000000
Binary files a/content/project/personality-diabetes/featured.jpg and /dev/null differ
diff --git a/content/project/personality-diabetes/featured.png b/content/project/personality-diabetes/featured.png
new file mode 100644
index 0000000..a4830ae
Binary files /dev/null and b/content/project/personality-diabetes/featured.png differ
diff --git a/content/project/personality-diabetes/index.md b/content/project/personality-diabetes/index.md
index caee6fd..6fbf1a6 100644
--- a/content/project/personality-diabetes/index.md
+++ b/content/project/personality-diabetes/index.md
@@ -1,6 +1,6 @@
---
title: Predicting diabetes status from personality
-summary: A machine learning project
+summary: A machine learning project exploring the relationship between diabetes and personality
abstract: ""
date: "2020-04-24T00:00:00Z"
image:
@@ -15,11 +15,16 @@ links:
icon_pack: fas
name: Pre-registration
url: https://osf.io/nqs8e/
-
+- icon: info-circle
+ icon_pack: fas
+ name: SAPA Project
+ url: https://www.sapa-project.org/
+
tags:
- machine learning
- health
- R
---
+![](model_performance.png)
Prior research suggests that diabetes is both a cause and consequence of various health behaviors and thus has complex links to personality. This study investigates the utility of personality in predicting diabetes status (Type 1, Type 2 or none) using a subset of items from the Synthetic Aperture Personality Assessment (SAPA) Project (N ≈ 645,000). We estimate the classification accuracy of various personality measures, including low- and high-dimensional data, using supervised machine learning techniques, e.g. random forests, support vector machines and neural networks. Results are compared across machine learning models and dimensionality of personality predictors. This project involves the automated generation of executable R scripts using non-standard evaluation within a tidyverse framework, allowing for parallel processing on high-performance computing clusters. This analysis informs the extent to which personality measurement could be applied in clinical contexts related to diabetes.
\ No newline at end of file
diff --git a/content/project/personality-diabetes/model_performance.png b/content/project/personality-diabetes/model_performance.png
new file mode 100644
index 0000000..09bc0f8
Binary files /dev/null and b/content/project/personality-diabetes/model_performance.png differ
diff --git a/content/project/rstudio-instructor-certification/certificate.jpeg b/content/project/rstudio-instructor-certification/certificate.jpeg
new file mode 100644
index 0000000..b345a83
Binary files /dev/null and b/content/project/rstudio-instructor-certification/certificate.jpeg differ
diff --git a/content/project/rstudio-instructor-certification/featured.jpg b/content/project/rstudio-instructor-certification/featured.jpg
deleted file mode 100644
index 25492b4..0000000
Binary files a/content/project/rstudio-instructor-certification/featured.jpg and /dev/null differ
diff --git a/content/project/rstudio-instructor-certification/featured.png b/content/project/rstudio-instructor-certification/featured.png
new file mode 100644
index 0000000..c53fe7c
Binary files /dev/null and b/content/project/rstudio-instructor-certification/featured.png differ
diff --git a/content/project/rstudio-instructor-certification/index.md b/content/project/rstudio-instructor-certification/index.md
index abef6e0..ee6a093 100644
--- a/content/project/rstudio-instructor-certification/index.md
+++ b/content/project/rstudio-instructor-certification/index.md
@@ -7,24 +7,29 @@ image:
caption:
focal_point: Smart
links:
-- icon: address-card
+- icon: book
icon_pack: fas
- name: Trainer Directory
- url: https://education.rstudio.com/trainers/people/cullen+brendan/
+ name: Blog post
+ url: /post/2020-09-03-reflections-on-rstudio-instructor-training/index.html
- icon: github
icon_pack: fab
- name: Demonstration Lesson Repo
+ name: Demo Lesson Repo
url: https://github.com/brendanhcullen/rstudio-instructor-certification
-- icon: book
+- icon: file-code
icon_pack: fas
- name: Blog post
- url: /post/2020-09-03-reflections-on-rstudio-instructor-training/index.html
+ name: Sample exam solutions
+ url: https://tidyverse-exam-v2-solutions.netlify.app/
+- icon: address-card
+ icon_pack: fas
+ name: Trainer Directory
+ url: https://education.rstudio.com/trainers/people/cullen+brendan/
tags:
- R
- education
---
+![](certificate.jpeg)
I recently went through RStudio's [Instructor Training and Certification Program](https://education.rstudio.com/trainers/), and I am now an RStudio Certified Instructor in the [tidyverse](https://www.tidyverse.org/). You can read more details in the links above.
-If you'd like to hire me to lead a workshop or training for your group, please don't hesitate to [reach out](mailto:bcullen@uoregon.edu). I would love to hear from you!
\ No newline at end of file
+If you'd like to hire me to lead a workshop or training for your group, please don't hesitate to [reach out](mailto:bcullen@uoregon.edu). I would love to hear from you!
diff --git a/content/project/tidyverse-sample-exam-solutions/featured.png b/content/project/tidyverse-sample-exam-solutions/featured.png
deleted file mode 100644
index 0942b2a..0000000
Binary files a/content/project/tidyverse-sample-exam-solutions/featured.png and /dev/null differ
diff --git a/content/project/tidyverse-sample-exam-solutions/index.md b/content/project/tidyverse-sample-exam-solutions/index.md
deleted file mode 100644
index 4431e8d..0000000
--- a/content/project/tidyverse-sample-exam-solutions/index.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-date: "2020-09-10"
-external_link: https://tidyverse-exam-v2-solutions.netlify.app/
-image:
- caption:
- focal_point: Smart
-summary: A solution guide to the sample tidyverse exam v2.0 for the RStudio Instructor Training and Certification Program.
-tags:
-- R
-- education
-
-title: Tidyverse Sample Exam 2.0 Solutions
----
-
diff --git a/content/project/uopsych-r-bootcamp/featured.jpg b/content/project/uopsych-r-bootcamp/featured.jpg
index fbc8e97..854bb1a 100644
Binary files a/content/project/uopsych-r-bootcamp/featured.jpg and b/content/project/uopsych-r-bootcamp/featured.jpg differ
diff --git a/content/project/uopsych-r-bootcamp/index.md b/content/project/uopsych-r-bootcamp/index.md
index 698348b..527c973 100644
--- a/content/project/uopsych-r-bootcamp/index.md
+++ b/content/project/uopsych-r-bootcamp/index.md
@@ -1,5 +1,5 @@
---
-title: UO Psych R Bootcamp 2020
+title: UO Psych R Bootcamp
summary: Materials from a 3-day bootcamp that introduces new learners to R, RStudio and the tidyverse.
abstract: ""
date: "2020-10-06T00:00:00Z"
@@ -9,11 +9,19 @@ image:
links:
- icon: link
icon_pack: fas
- name: Bootcamp Website
+ name: 2021 Bootcamp Website
+ url: https://uopsych-r-bootcamp-2021.netlify.app/
+- icon: github
+ icon_pack: fab
+ name: 2021 Github Repo
+ url: https://github.com/uopsych/summeR-bootcamp-2021
+- icon: link
+ icon_pack: fas
+ name: 2020 Bootcamp Website
url: https://uopsych-r-bootcamp-2020.netlify.app/
- icon: github
icon_pack: fab
- name: Github Repo
+ name: 2020 Github Repo
url: https://github.com/uopsych/summeR-bootcamp-2020
- icon: book
icon_pack: fas
@@ -25,30 +33,38 @@ tags:
- education
---
-I organized and taught a 3-day introductory R Bootcamp for my fellow ducks in the Department of Psychology at the University of Oregon in September 2020. We had we had a fantastic mix of participants, including incoming PhD and master's students, current grad students, undergrads, research staff, and faculty, with over 40 people attending each day. Thanks so much to everyone who participated! :duck:
+I organized and taught a 3-day introductory R Bootcamp for the Department of Psychology at the University of Oregon. We had we had a fantastic mix of participants, including incoming PhD and master's students, current grad students, undergrads, research staff, and faculty. Thanks so much to everyone who participated!
+
+The materials have been designed such that you should be able to work through the slides and exercises at your own pace if you were not able to attend the bootcamp sessions. All materials are available on the bootcamp website: https://uopsych-r-bootcamp-2021.netlify.app/
-The materials have been designed such that you should be able to work through the slides and exercises at your own pace if you were not able to attend the bootcamp sessions. All materials are available on the bootcamp website: https://uopsych-r-bootcamp-2020.netlify.app/
+
+
+
***
This bootcamp gives a gentle introduction to R and RStudio, transforming and visualizing data with the tidyverse, and the basics of R Markdown. It assumes no prior experience with R or any other programming language and is designed to get learners up and running with the most widely useful tools for reproducible data analysis in R while emphasizing best practices for writing code and organizing project-oriented workflows.
-It also contains a curated list of resources for each topic for those who want more opportunities for further learning and practice, as well as a collection of more generally useful [resources](https://uopsych-r-bootcamp-2020.netlify.app/resources/) for learning R.
+It also contains a curated list of resources for each topic for those who want more opportunities for further learning and practice, as well as a collection of more generally useful [resources](https://uopsych-r-bootcamp-2021.netlify.app/resources/) for learning R.
Specific topics include:
-1. [Basics of R & RStudio](https://uopsych-r-bootcamp-2020.netlify.app/post/01-r-basics/)
-2. [Data Types & Structures](https://uopsych-r-bootcamp-2020.netlify.app/post/02-data-types)
-3. [Functions & Debugging](https://uopsych-r-bootcamp-2020.netlify.app/post/03-functions/)
-4. [Introduction to the Tidyverse](https://uopsych-r-bootcamp-2020.netlify.app/post/04-intro-tidyverse/)
-5. [Importing Data & Project-oriented Workflows](https://uopsych-r-bootcamp-2020.netlify.app/post/05-importing-workflows/)
-6. [Data Visualization with {ggplot2}](https://uopsych-r-bootcamp-2020.netlify.app/post/06-ggplot2/)
-7. [Data Wrangling with {dplyr}](https://uopsych-r-bootcamp-2020.netlify.app/post/07-dplyr/)
-8. [Data Tidying with {tidyr}](https://uopsych-r-bootcamp-2020.netlify.app/post/08-tidyr/)
-9. [Reproducible Reporting with R Markdown](https://uopsych-r-bootcamp-2020.netlify.app/post/09-rmarkdown/)
+1. [Basics of R & RStudio](https://uopsych-r-bootcamp-2021.netlify.app/post/01-r-basics/)
+2. [Data Types & Structures](https://uopsych-r-bootcamp-2021.netlify.app/post/02-data-types)
+3. [Functions & Debugging](https://uopsych-r-bootcamp-2021.netlify.app/post/03-functions/)
+4. [Introduction to the Tidyverse](https://uopsych-r-bootcamp-2021.netlify.app/post/04-intro-tidyverse/)
+5. [Importing Data & Project-oriented Workflows](https://uopsych-r-bootcamp-2021.netlify.app/post/05-importing-workflows/)
+6. [Data Visualization with ggplot2](https://uopsych-r-bootcamp-2021.netlify.app/post/06-ggplot2/)
+7. [Data Wrangling with dplyr](https://uopsych-r-bootcamp-2021.netlify.app/post/07-dplyr/)
+8. [Data Tidying with tidyr](https://uopsych-r-bootcamp-2021.netlify.app/post/08-tidyr/)
+9. [Reproducible Reporting with R Markdown](https://uopsych-r-bootcamp-2021.netlify.app/post/09-rmarkdown/)
***
-This work is [licensed](https://github.com/uopsych/summeR-bootcamp-2020/blob/master/LICENSE.md) under a Creative Commons Attribution 4.0 International License. Please feel free to share and/or adapt and re-use any of the [materials](https://github.com/uopsych/summeR-bootcamp-2020) for your own teaching!
+This work is [licensed](https://github.com/uopsych/summeR-bootcamp-2021/blob/main/LICENSE.md) under a Creative Commons Attribution 4.0 International License. Please feel free to share and/or adapt and re-use any of the [materials](https://github.com/uopsych/summeR-bootcamp-2021) for your own teaching!
-You can read more about the bootcamp in this [blog post](/post/2020-10-19-teaching-an-r-bootcamp-remotely/index.html).
\ No newline at end of file
+You can read more about the bootcamp in this [blog post](/blog/2020-10-19-teaching-an-r-bootcamp-remotely/).
\ No newline at end of file
diff --git a/content/project_landing/index.md b/content/project_landing/index.md
deleted file mode 100644
index 218eb4a..0000000
--- a/content/project_landing/index.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "Projects" # Add a page title.
-summary: "Hello!" # Add a page description.
-date: "2019-01-01T00:00:00Z" # Add today's date.
-type: "widget_page" # Page type is a Widget Page
----
\ No newline at end of file
diff --git a/content/project_landing/projects.md b/content/project_landing/projects.md
deleted file mode 100644
index 926f86d..0000000
--- a/content/project_landing/projects.md
+++ /dev/null
@@ -1,96 +0,0 @@
-+++
-# A Projects section created with the Portfolio widget.
-widget = "portfolio" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = true # Activate this widget? true/false
-weight = 65 # Order that this section will appear.
-
-title = "Projects"
-subtitle = "An assortment of different projects I have worked on during my time in graduate school. Wherever possible, I have shared the code for each of these projects on [Github](https://github.com/brendanhcullen) -- any comments, pull requests, or feedback of any kind are more than welcome!"
-
-
-[content]
- # Page type to display. E.g. project.
- page_type = "project"
-
- # Filter toolbar (optional).
- # Add or remove as many filters (`[[content.filter_button]]` instances) as you like.
- # To show all items, set `tag` to "*".
- # To filter by a specific tag, set `tag` to an existing tag name.
- # To remove toolbar, delete/comment all instances of `[[content.filter_button]]` below.
-
- # Default filter index (e.g. 0 corresponds to the first `[[filter_button]]` instance below).
- filter_default = 0
-
- [[content.filter_button]]
- name = "All"
- tag = "*"
-
- [[content.filter_button]]
- name = "R"
- tag = "R"
-
- [[content.filter_button]]
- name = "education"
- tag = "education"
-
- [[content.filter_button]]
- name = "data viz"
- tag = "data viz"
-
- [[content.filter_button]]
- name = "neuroscience"
- tag = "neuroscience"
-
-
- [[content.filter_button]]
- name = "health"
- tag = "health"
-
-
- [[content.filter_button]]
- name = "machine learning"
- tag = "machine learning"
-
-[design]
- # Choose how many columns the section has. Valid values: 1 or 2.
- columns = "2"
-
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 5 = Showcase
- view = 3
-
- # For Showcase view, flip alternate rows?
- flip_alt_rows = false
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
-
diff --git a/content/talk/2020-wisely/featured.jpg b/content/talk/2020-wisely/featured.jpg
new file mode 100644
index 0000000..82774f4
Binary files /dev/null and b/content/talk/2020-wisely/featured.jpg differ
diff --git a/content/talk/2020-wisely/index.md b/content/talk/2020-wisely/index.md
new file mode 100644
index 0000000..3019d31
--- /dev/null
+++ b/content/talk/2020-wisely/index.md
@@ -0,0 +1,43 @@
+---
+title: 'Using R more "wisely": Column-wise & row-wise operations with dplyr'
+draft: false
+event: 'R Ladies Algiers'
+event_url: https://www.meetup.com/rladies-algiers/events/274647307/
+location:
+summary: "Workshop for R-Ladies Algiers on column-wise and row-wise operations with dplyr for more efficient data wrangling and summarizing."
+
+# Talk start and end times.
+# End time can optionally be hidden by prefixing the line with `#`.
+date: "2020-11-24T09:30:00Z"
+date_end:
+all_day: false
+publishdate:
+categories:
+ - workshop
+tags:
+ - dplyr
+lastmod:
+featured: no
+image:
+ focal_point: 'center'
+ preview_only: no
+projects: []
+links:
+- icon: door-open
+ icon_pack: fas
+ name: slides
+ url: https://dplyr-wisely.netlify.app/
+- icon: github
+ icon_pack: fab
+ name: materials
+ url: https://github.com/brendanhcullen/wisely
+---
+
+
+
+
+
diff --git a/content/talk/_index.md b/content/talk/_index.md
index ee3a735..49289a9 100644
--- a/content/talk/_index.md
+++ b/content/talk/_index.md
@@ -1,7 +1,25 @@
---
-header:
- caption: ""
- image: ""
-title: Recent & Upcoming Talks
-view: 2
+title: Talks & Workshops
+description:
+author: "Brendan Cullen"
+show_post_thumbnail: true
+thumbnail_left: false
+show_author_byline: false
+show_post_date: true
+show_post_time: false
+# for listing page layout
+layout: list # list, list-sidebar
+
+# set up common front matter for all pages inside blog/
+cascade:
+ author: "Brendan Cullen"
+ show_author_byline: false
+ show_post_date: true
+ show_post_time: false
+ show_comments: false # see site config to choose Disqus or Utterances
+ # for single-sidebar layout
+ sidebar:
+ text_link_label: View recent events
+ text_link_url: /talk/
+ show_sidebar_adunit: false # show ad container
---
diff --git a/content/talk/example/featured.jpg b/content/talk/example/featured.jpg
deleted file mode 100644
index 7b16c3c..0000000
Binary files a/content/talk/example/featured.jpg and /dev/null differ
diff --git a/content/talk/example/index.md b/content/talk/example/index.md
deleted file mode 100644
index 07c39d9..0000000
--- a/content/talk/example/index.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-abstract: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis posuere tellusac
- convallis placerat. Proin tincidunt magna sed ex sollicitudin condimentum. Sed ac
- faucibus dolor, scelerisque sollicitudin nisi. Cras purus urna, suscipit quis sapien
- eu, pulvinar tempor diam.
-address:
- city: Stanford
- country: United States
- postcode: "94305"
- region: CA
- street: 450 Serra Mall
-all_day: false
-authors: []
-date: "2030-06-01T13:00:00Z"
-date_end: "2030-06-01T15:00:00Z"
-event: Academic Theme Conference
-event_url: https://example.org
-featured: false
-image:
- caption: 'Image credit: [**Unsplash**](https://unsplash.com/photos/bzdhc5b3Bxs)'
- focal_point: Right
-links:
-- icon: twitter
- icon_pack: fab
- name: Follow
- url: https://twitter.com/georgecushen
-location: Source Themes HQ
-math: true
-projects:
-- internal-project
-publishDate: "2017-01-01T00:00:00Z"
-slides: example
-summary: An example talk using Academic's Markdown slides feature.
-tags: []
-title: Example Talk
-url_code: ""
-url_pdf: ""
-url_slides: ""
-url_video: ""
----
-
-{{% alert note %}}
-Click on the **Slides** button above to view the built-in slides feature.
-{{% /alert %}}
-
-Slides can be added in a few ways:
-
-- **Create** slides using Academic's [*Slides*](https://sourcethemes.com/academic/docs/managing-content/#create-slides) feature and link using `slides` parameter in the front matter of the talk file
-- **Upload** an existing slide deck to `static/` and link using `url_slides` parameter in the front matter of the talk file
-- **Embed** your slides (e.g. Google Slides) or presentation video on this page using [shortcodes](https://sourcethemes.com/academic/docs/writing-markdown-latex/).
-
-Further talk details can easily be added to this page using *Markdown* and $\rm \LaTeX$ math code.
diff --git a/layouts/_default/rss.xml b/layouts/_default/rss.xml
new file mode 100644
index 0000000..3672f5a
--- /dev/null
+++ b/layouts/_default/rss.xml
@@ -0,0 +1,47 @@
+{{- $pctx := . -}}
+{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
+{{- $pages := slice -}}
+
+{{- if $.IsHome -}}
+{{- $pages = $pctx.RegularPages -}}
+
+{{- else if $.IsSection -}}
+{{- $pages = .RegularPagesRecursive -}}
+
+{{- else -}}
+{{- $pages = $pctx.Pages -}}
+{{- end -}}
+
+{{- $limit := .Site.Config.Services.RSS.Limit -}}
+{{- if ge $limit 1 -}}
+{{- $pages = $pages | first $limit -}}
+{{- end -}}
+{{- printf "" | safeHTML }}
+
+
+ {{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}
+ {{ .Permalink }}
+ Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}
+ Hugo -- gohugo.io{{ with .Site.LanguageCode }}
+ {{.}}{{end}}{{ with .Site.Author.email }}
+ {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Author.email }}
+ {{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}{{ with .Site.Copyright }}
+ {{.}}{{end}}{{ if not .Date.IsZero }}
+ {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}{{ end }}
+ {{- with .OutputFormats.Get "RSS" -}}
+ {{ printf "" .Permalink .MediaType | safeHTML }}
+ {{- end -}}
+ {{ range $pages.ByDate.Reverse }}
+
+ {{ .Title }}
+ {{ .Permalink }}
+ {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}
+ {{ with .Site.Author.email }}{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}{{end}}
+ {{ .Permalink }}
+ {{ .Content | html }}
+
+ {{ end }}
+
+
+
+
diff --git a/layouts/blog/single-sidebar.html b/layouts/blog/single-sidebar.html
new file mode 100644
index 0000000..4dda3f8
--- /dev/null
+++ b/layouts/blog/single-sidebar.html
@@ -0,0 +1,35 @@
+{{ define "main" }}
+
+
+
+
+
{{ .Title }}
+ {{ if .Params.subtitle }}
{{ .Params.subtitle }}
{{ end }}
+ {{ if .Params.show_author_byline }}
{{ if .Params.author }}By {{ .Params.author }}{{ end }}{{ with .Params.categories }} in{{ range . }} {{ . }} {{ end }}{{ end }}
{{ end }}
+ {{ if .Params.show_post_date }}
{{ .PublishDate.Format "January 2, 2006" }}
{{ end }}
+ {{ if .Params.links }}
+
+ {{ partial "shared/btn-links.html" . }}
+
+ {{ end }}
+
+
+ {{ .Content }}
+
+
+
+ {{ if .Params.show_comments }}
+ {{ partial "shared/comments.html" . }}
+ {{ end }}
+
+
+
+{{ end }}
diff --git a/layouts/partials/shared/event-details.html b/layouts/partials/shared/event-details.html
new file mode 100644
index 0000000..c7ba1e4
--- /dev/null
+++ b/layouts/partials/shared/event-details.html
@@ -0,0 +1,43 @@
+
+ {{ with .Params.excerpt }}
+
diff --git a/layouts/shortcodes/diagram.html b/layouts/shortcodes/diagram.html
new file mode 100644
index 0000000..33fdc82
--- /dev/null
+++ b/layouts/shortcodes/diagram.html
@@ -0,0 +1,3 @@
+
+ {{- safeHTML .Inner -}}
+
\ No newline at end of file
diff --git a/layouts/shortcodes/figure.html b/layouts/shortcodes/figure.html
new file mode 100644
index 0000000..eff1c44
--- /dev/null
+++ b/layouts/shortcodes/figure.html
@@ -0,0 +1,36 @@
+{{/* Enable image to be loaded from local page dir or media library at `static/img/`. */}}
+{{ $image_src := .Get "src" }}
+{{ if .Get "library" }}
+ {{ $image_src = printf "img/%s" $image_src | relURL }}
+{{ end }}
+
+{{/* Disallow user from opening image in the lightbox? */}}
+{{ $lightbox := eq (.Get "lightbox" | default "true") "true" }}
+
+{{/* Get lightbox group for showing multiple images in a lightbox. */}}
+{{ $group := .Get "lightbox-group" | default "" }}
+
+{{/* Get caption. Support legacy `title` option. */}}
+{{ $caption := .Get "title" | default (.Get "caption") | default "" }}
+
+
diff --git a/layouts/shortcodes/fragment.html b/layouts/shortcodes/fragment.html
new file mode 100644
index 0000000..312208b
--- /dev/null
+++ b/layouts/shortcodes/fragment.html
@@ -0,0 +1,3 @@
+
+ {{ .Inner }}
+
\ No newline at end of file
diff --git a/layouts/shortcodes/gallery.html b/layouts/shortcodes/gallery.html
new file mode 100644
index 0000000..dc8bc55
--- /dev/null
+++ b/layouts/shortcodes/gallery.html
@@ -0,0 +1,56 @@
+{{/* Get album folder or default to `gallery/`. */}}
+{{ $album := "" }}
+{{ with .Get "album" }}{{ $album = . }}{{else}}{{ $album = "gallery" }}{{end}}
+
+{{/* Set image path and page bundle that images are associated with. */}}
+{{ $album_path := "" }}
+{{ $resource_page := "" }}
+{{ if eq .Page.Parent.Type "widget_page" }}
+ {{ $album_path = printf "%s/%s/*" (path.Base (path.Split .Page.Path).Dir) $album }}
+ {{ $resource_page = $.Page.Parent }}
+{{ else }}
+ {{ $album_path = printf "%s/*" $album }}
+ {{ $resource_page = $.Page }}
+{{ end }}
+
+
+
+ {{/* Attempt to automatically load gallery images from page bundle */}}
+ {{ $images := ($resource_page.Resources.ByType "image").Match $album_path }}
+ {{ with $images }}
+ {{ range $images }}
+ {{ $image := .Resize "x190" }}
+ {{/* Check if the user set a caption for this image */}}
+ {{ $filename := path.Base .Name }}
+ {{ $caption := "" }}
+ {{ if $.Page.Params.gallery_item }}
+ {{ range (where (where $.Page.Params.gallery_item "album" $album) "image" $filename) }}
+ {{ $caption = .caption }}
+ {{ end }}
+ {{ end }}
+
+
+
+ {{end}}
+
+ {{else}}
+ {{/* Load gallery images from the `static/img/` media library or internet */}}
+
+ {{ if $.Page.Params.gallery_item }}
+ {{ range (where $.Page.Params.gallery_item "album" $album) }}
+ {{/* Set image path. */}}
+ {{ $.Scratch.Set "src" .image }}
+ {{ if gt (len .image) 4 }}
+ {{ if ne "http" (slicestr .image 0 4) }}
+ {{ $.Scratch.Set "src" (printf "img/%s" .image | relURL) }}
+ {{ end }}
+ {{ end }}
+
+
+
+ {{end}}
+ {{else}}
+ {{ errorf "Unable to load gallery in %s." .Page.File.Filename }}
+ {{end}}
+ {{end}}
+
\ No newline at end of file
diff --git a/layouts/shortcodes/gdocs.html b/layouts/shortcodes/gdocs.html
new file mode 100644
index 0000000..aa3ad33
--- /dev/null
+++ b/layouts/shortcodes/gdocs.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/layouts/shortcodes/hl.html b/layouts/shortcodes/hl.html
new file mode 100644
index 0000000..f56cb01
--- /dev/null
+++ b/layouts/shortcodes/hl.html
@@ -0,0 +1 @@
+{{ .Inner | markdownify | emojify }}
\ No newline at end of file
diff --git a/layouts/shortcodes/icon.html b/layouts/shortcodes/icon.html
new file mode 100644
index 0000000..38541ab
--- /dev/null
+++ b/layouts/shortcodes/icon.html
@@ -0,0 +1,10 @@
+{{- if (.Get "name") -}}
+ {{- $icon := .Get "name" -}}
+ {{- $pack := or (.Get "pack") "fas" -}}
+ {{- $pack_prefix := $pack -}}
+ {{- if in (slice "fab" "fas" "far" "fal") $pack -}}
+ {{- $pack_prefix = "fa" -}}
+ {{- end -}}
+ {{- $padding_right := (.Get "padding_right") | default 1 -}}{{/* Defaulting to 1 prevents no spacing when minimizing HTML. */}}
+
+{{- end -}}
\ No newline at end of file
diff --git a/layouts/shortcodes/list_categories.html b/layouts/shortcodes/list_categories.html
new file mode 100644
index 0000000..7bbf986
--- /dev/null
+++ b/layouts/shortcodes/list_categories.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/layouts/shortcodes/list_tags.html b/layouts/shortcodes/list_tags.html
new file mode 100644
index 0000000..4384812
--- /dev/null
+++ b/layouts/shortcodes/list_tags.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/layouts/shortcodes/staticref.html b/layouts/shortcodes/staticref.html
new file mode 100644
index 0000000..c6e99f4
--- /dev/null
+++ b/layouts/shortcodes/staticref.html
@@ -0,0 +1 @@
+{{ .Inner }}
\ No newline at end of file
diff --git a/layouts/shortcodes/toc.html b/layouts/shortcodes/toc.html
new file mode 100644
index 0000000..31dd72c
--- /dev/null
+++ b/layouts/shortcodes/toc.html
@@ -0,0 +1,2 @@
+
+
+## Use attractive system fonts
+
+Alternatively, you may want to use a system font, which you know will be rendered reliably across languages, operating systems, and browsers. Apéro uses [Tachyons](https://tachyons.io) to render beautiful system font stacks for your site, making it super simple to configure and blazing fast to load. The default choices are `sans-serif` or `serif`, and can be assigned to headings and body text, respectively. Additional options can be found in the [Tachyons Font Family Reference](https://tachyons.io/docs/typography/font-family/). Why use system fonts?
+
+> Relying on systems fonts greatly improves page performance and can also help your web application/site blend in with the user’s operating system. Readability is strongly linked to familiarity, so this helps create a more fluid reading experience, allowing your users to focus on your content.
+>
+> — [Tachyons typography docs](http://tachyons.io/docs/typography/font-family/)
+
+Here is a step-by-step, using the `config.toml` file:
+
++ Leave both `customtextFontFamily` and `customheadingFontFamily` blank (with empty quotes, or comment out the line entirely).
+
++ Just below those keys, select a `textFontFamily` and `headingFontFamily` from the options listed [here](http://tachyons.io/docs/typography/font-family/). All values are lower case, and exclude the `.` in front.
+
+```toml
+[params]
+
+ # use an embedded font-family
+ # serif options: Fraunces / EB Garamond / Bitter
+ # sans-serif options: Commissioner / Alegreya Sans / Metropolis
+ # if you import your own fonts, name them here too
+ customtextFontFamily = ""
+ customheadingFontFamily = ""
+
+ # alternatively, leave empty and select basic font options: sans-serif or serif
+ # for more http://tachyons.io/docs/typography/font-family/
+ textFontFamily = "sans-serif"
+ headingFontFamily = "serif"
+```
+
+For example, you may choose:
+```toml
+ textFontFamily = "courier"
+ headingFontFamily = "baskerville"
+```
+
+And your site would look like:
+
+![](system-font.png)
+
+## Use a custom font
+
+Alright alright alright. So you still want to use your own fonts. You'll need to do a bit more work to get this working, but not too much. If you made it here, I'm going to hope that you know a bit more about [self-hosting fonts](https://www.tunetheweb.com/blog/should-you-self-host-google-fonts/).
+
+Here are the steps:
+
++ Create a `static/fonts/` folder, and add the actual font files you'd like to embed to that folder. To download Google fonts, there is a [popular app](https://google-webfonts-helper.herokuapp.com/fonts) to help you. Select a font, then download the zip file containing the font files you'll need to embed.
+
++ Create an `assets/` folder in the root of your website project (don't add it to your `themes/` directory!).
+
++ Create a file named `custom.scss` in the new `assets/` folder to define the [`@font-face` CSS rule](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) for each font/weight combination you downloaded. For example, here is a `custom.scss` that imports the [Nanum Myeongjo font](https://fonts.google.com/specimen/Nanum+Myeongjo). The [webfonts helper app](https://google-webfonts-helper.herokuapp.com/fonts) will help write your CSS for you (using `../fonts/` to customize the folder prefix correctly by default), like this:
+
+```scss
+/* nanum-myeongjo-regular - latin */
+@font-face {
+ font-family: 'Nanum Myeongjo';
+ font-style: normal;
+ font-weight: 400;
+ src: local(''),
+ url('../fonts/nanum-myeongjo-v15-latin-regular.woff2') format('woff2'),
+ url('../fonts/nanum-myeongjo-v15-latin-regular.woff') format('woff');
+}
+```
+
+Your final step is to go back to your `config.toml` file and add the `font-family` values for the font(s) you want to use to the `customtextFontFamily` and/or `customheadingFontFamily` keys. You can combine custom fonts with system fonts too.
+
+```toml
+[params]
+
+ # use an embedded font-family
+ # serif options: Fraunces / EB Garamond / Bitter
+ # sans-serif options: Commissioner / Alegreya Sans / Metropolis
+ # if you import your own fonts, name them here too
+ customtextFontFamily = ""
+ customheadingFontFamily = "Nanum Myeongjo"
+
+ # alternatively, leave empty and select basic font options: sans-serif or serif
+ # for more http://tachyons.io/docs/typography/font-family/
+ textFontFamily = "sans-serif"
+ headingFontFamily = ""
+```
+
+Here is what this could look like (thanks to workshop participant [Issac Lee](https://github.com/issactoast)!)
+
+![](isaac-font.png)
+
+If you do all this, you have my consent to delete the theme's `static/fonts/` folder that holds all the custom embedded fonts so you aren't carrying those unnecessary files around with your site (do not delete the `static/webfonts/` folder- that holds the [Font Awesome icons](https://fontawesome.com/)!).
+
+For example, let's examine the 3 commits necessary to make [this magic](https://google-webfonts-helper.herokuapp.com/fonts/hachi-maru-pop?subsets=latin) happen:
+
+### Commit #1
+
+![](font-static-files.png)
+
+### Commit #2
+
+![](font-assets-css.png)
+
+### Commit #3
+
+![](font-config.png)
+
+### Final result
+
+![](hachi-font.png)
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/fonts/isaac-font.png b/themes/hugo-apero/exampleSite/content/blog/fonts/isaac-font.png
new file mode 100644
index 0000000..c1ac3f4
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/fonts/isaac-font.png differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/fonts/system-font.png b/themes/hugo-apero/exampleSite/content/blog/fonts/system-font.png
new file mode 100644
index 0000000..f5609f4
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/fonts/system-font.png differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/fonts/tachyons-logo-script.png b/themes/hugo-apero/exampleSite/content/blog/fonts/tachyons-logo-script.png
new file mode 100644
index 0000000..58a2645
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/fonts/tachyons-logo-script.png differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.Rmarkdown b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.Rmarkdown
new file mode 100644
index 0000000..8552b5f
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.Rmarkdown
@@ -0,0 +1,33 @@
+---
+title: "An Rmarkdown post"
+subtitle: ""
+excerpt: "testing the excerpt field"
+date: 2020-12-30
+author: "Alison Hill"
+draft: false
+images:
+series:
+tags:
+categories:
+layout: single
+---
+
+
+## Air quality
+
+```{r}
+with(airquality, boxplot(Temp ~ Month))
+```
+
+
+```{r}
+with(airquality, plot(Ozone ~ Temp))
+```
+
+```{r}
+mlev <- levels(with(airquality, as.factor(Month)))
+with(airquality, plot(Ozone ~ Temp,
+ pch = as.numeric(mlev),
+ col = mlev))
+```
+
diff --git a/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.html b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.html
new file mode 100644
index 0000000..3590609
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.html
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+An Rmarkdown post
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.markdown b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.markdown
new file mode 100644
index 0000000..d16dca9
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/rmarkdown/index.markdown
@@ -0,0 +1,42 @@
+---
+title: "An Rmarkdown post"
+subtitle: ""
+excerpt: "testing the excerpt field"
+date: 2020-12-30
+author: "Alison Hill"
+draft: false
+images:
+series:
+tags:
+categories:
+layout: single
+---
+
+
+## Air quality
+
+
+```r
+with(airquality, boxplot(Temp ~ Month))
+```
+
+
+
+
+
+```r
+with(airquality, plot(Ozone ~ Temp))
+```
+
+
+
+
+```r
+mlev <- levels(with(airquality, as.factor(Month)))
+with(airquality, plot(Ozone ~ Temp,
+ pch = as.numeric(mlev),
+ col = mlev))
+```
+
+
+
diff --git a/themes/hugo-apero/exampleSite/content/blog/seedling/featured.jpg b/themes/hugo-apero/exampleSite/content/blog/seedling/featured.jpg
new file mode 100644
index 0000000..b319027
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/seedling/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/seedling/index.md b/themes/hugo-apero/exampleSite/content/blog/seedling/index.md
new file mode 100644
index 0000000..f0c669a
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/seedling/index.md
@@ -0,0 +1,72 @@
+---
+title: "Using panelsets"
+subtitle: "How to add panelsets in plain markdown posts."
+excerpt: "Add tabbed sections to your posts."
+date: 2021-01-02
+author: "Alison Hill"
+draft: false
+# layout options: single, single-sidebar
+layout: single
+categories:
+- Theme features
+---
+
+Courtesy of panelset.js by Garrick Aden-Buie, from his xaringanExtra package: https://pkg.garrickadenbuie.com/xaringanExtra/#/panelset
+
+For example, this panelset:
+
+{{< panelset class="greetings" >}}
+{{< panel name="Hello! :wave:" >}}
+ hello
+{{< /panel >}}
+{{< panel name="Goodbye :dash:" >}}
+ goodbye
+{{< /panel >}}
+{{< /panelset >}}
+
+Was created by combining this theme's `panelset` and `panel` shortcodes:
+
+```go
+{{* panelset class="greetings" */>}}
+{{* panel name="Hello! :wave:" */>}}
+ hello
+{{* /panel */>}}
+{{* panel name="Goodbye :dash:" */>}}
+ goodbye
+{{* /panel */>}}
+{{* /panelset */>}}
+```
+
+
+You could also revert to HTML as well. For example, this panelset:
+
+
+
+
+
Question
+
+
Which came first: the :chicken: or the :egg:?
+
+
+
Answer :hatching_chick:
+
+
Team :egg: FTW!
+
+
+
+Was created with this HTML code:
+
+```html
+
+
+
Question
+
+
Which came first: the :chicken: or the :egg:?
+
+
+
Answer :hatching_chick:
+
+
Team :egg: FTW!
+
+
+```
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/sidebar-listing.jpg b/themes/hugo-apero/exampleSite/content/blog/sidebar-listing.jpg
new file mode 100644
index 0000000..043295e
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/sidebar-listing.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/social/featured.jpg b/themes/hugo-apero/exampleSite/content/blog/social/featured.jpg
new file mode 100644
index 0000000..f43193a
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/social/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/social/index.md b/themes/hugo-apero/exampleSite/content/blog/social/index.md
new file mode 100644
index 0000000..49115ea
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/social/index.md
@@ -0,0 +1,98 @@
+---
+title: "Set up your social"
+subtitle: "Social icons may appear on several pages throughout your site. Learn how to set them up, and control where they show up."
+excerpt: "This theme offers built-in Font Awesome icons for organizing your collection of social accounts and their links. Use icons to help visitors find you wherever you want to be found, and learn how to show or hide them in your site's header, footer, homepage, about page, and contact form."
+date: 2021-01-28
+author: "Alison Hill & Eric Anderson"
+draft: false
+# layout options: single, single-sidebar
+layout: single
+categories:
+- Theme Features
+---
+
+There are five places where you can choose to show social icons. Here is the tl;dr:
+
++ site header (set in `config.toml`),
++ site footer (set in `config.toml`),
++ [homepage](/) (set in `content/_index.md`),
++ [about page](/about) in the sidebar (set in `content/about/sidebar/index.md`), and
++ [contact page](/contact) (set in `content/form/contact.md`).
+
+Read on to learn how to set up your social icons, and how to show/hide them.
+
+## Configure social
+
+Wherever you end up wanting to show your social icons, you'll need to start by setting up the links in your site `config.toml` file. Open that up and scroll down to the `[[params.social]]` section. The start of it looks like this:
+
+```toml
+[params]
+
+
+ # Social icons may appear on your site header, footer, and other pages
+ # Add as many icons as you like below
+ # Icon pack "fab" includes brand icons, see: https://fontawesome.com/icons?d=gallery&s=brands&m=free
+ # Icon pack "fas" includes solid icons, see: https://fontawesome.com/icons?d=gallery&s=solid&m=free
+ # Icon pack "far" includes regular icons, see: https://fontawesome.com/icons?d=gallery&s=regular&m=free
+ [[params.social]]
+ icon = "github" # icon name without the 'fa-'
+ icon_pack = "fab"
+ url = "https://github.com/apreshill/apero"
+ [[params.social]]
+```
+
+For each link, you'll need to start a new portion that begins with `[[params.social]]`. Then, pick your `icon` and `icon_pack` from the [Font Awesome](https://fontawesome.com/) free icon library:
+
++ Icon pack "fab" includes [brand icons](https://fontawesome.com/icons?d=gallery&s=brands&m=free)
+
++ Icon pack "fas" includes [solid icons](https://fontawesome.com/icons?d=gallery&s=solid&m=free)
+
++ Icon pack "far" includes [regular icons](https://fontawesome.com/icons?d=gallery&s=regular&m=free)
+
+Finally, add the `url` that you would like users to go to when they click on that icon. All external links (i.e., those that start with `http`) will open in a new tab (that is, `target="_blank"`); relative links to pages within the site will open in the same window.
+
+Now you should be all set to show/hide your social icons. Each of these will pull the social icons and urls from the settings you just created in your site configuration file.
+
+## Show social in site header and footer
+
+Let's start with the header and footer, as those are site-wide. Open up your site `config.toml` file again and scroll down to the `[params]` section (it is actually :up: from where you configured these icons):
+
+```toml
+[params]
+
+
+ # show/hide social icons in site header & footer
+ # configure social icons and links below in [[params.social]]
+ socialInHeader = false
+ socialInFooter = true
+```
+
+That was easy!
+
+## Show social in homepage
+
+Open up `content/_index.md`. That file's YAML controls what you see on the homepage. Set `show_social_links` like so:
+
+```yaml
+show_social_links: true # specify social accounts in site config
+```
+
+If you set this to `true` to show the icons on the homepage, your social icons in the footer will not show up even when you set `socialInFooter = true`, so as not to litter your site with too many icons.
+
+## Show social in about page sidebar
+
+Open up `content/about/sidebar/index.md`. That file's YAML controls what you see in the sidebar on the about page. Set `show_social_links` like so:
+
+```yaml
+show_social_links: true # specify social accounts in site config
+```
+
+## Show social in contact page
+
+You may use the YAML for your contact page (located in `content/form/contact.md`):
+
+```yaml
+---
+show_social_links: true # specify social accounts in site config
+---
+```
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/01-spoonful.md b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/01-spoonful.md
new file mode 100644
index 0000000..74ed72b
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/01-spoonful.md
@@ -0,0 +1,25 @@
+---
+title: "A first post"
+weight: 1
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-01
+draft: false
+---
+
+{{< here >}}
+
+
+## does this work?
+
+### or this?
+
+---
+
+Let's start.
+
+## beginning
+
+## middle
+
+## end
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/index.md b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/index.md
new file mode 100644
index 0000000..3a1a8ad
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/index.md
@@ -0,0 +1,23 @@
+---
+title: "A second post"
+weight: 2
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-02
+draft: false
+---
+
+{{< here >}}
+
+
+## part 2!
+
+### does this work?
+
+---
+
+## now for some very cool things
+
+## more
+
+## get ready!
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/sidebar-inverse.jpg b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/sidebar-inverse.jpg
new file mode 100644
index 0000000..4e1e2ef
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/02-spoonful/sidebar-inverse.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/featured-photo.jpg b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/featured-photo.jpg
new file mode 100644
index 0000000..da4ff9c
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/featured-photo.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.Rmarkdown b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.Rmarkdown
new file mode 100644
index 0000000..dbc7b47
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.Rmarkdown
@@ -0,0 +1,19 @@
+---
+title: "A third post"
+weight: 3
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-03
+draft: false
+---
+
+{{< here >}}
+
+
+## are you still here?
+
+### does this work?
+
+---
+
+## final stretch!
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.html b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.html
new file mode 100644
index 0000000..720859a
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.html
@@ -0,0 +1,255 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A third post
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
A third post
+
2021-01-03
+
+
+
+
+
{{< here >}}
+
+
are you still here?
+
+
does this work?
+
+
+
+
+
final stretch!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.markdown b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.markdown
new file mode 100644
index 0000000..c7a3469
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/03-spoonful/index.markdown
@@ -0,0 +1,19 @@
+---
+title: "A third post"
+weight: 3
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-03
+draft: false
+---
+
+{{< here >}}
+
+
+## are you still here?
+
+### does this work?
+
+---
+
+## final stretch!
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/_index.md b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/_index.md
new file mode 100644
index 0000000..22a7698
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/_index.md
@@ -0,0 +1,46 @@
+---
+title: A Spoonful of Hugo
+description: |
+ A forking fun new feature for series.
+author: Alison Hill
+show_post_thumbnail: false
+show_author_byline: true
+show_post_date: true
+# for series listing page layout
+layout: list-sidebar # list, list-sidebar, list-grid
+
+# for list-sidebar layout
+sidebar:
+ title: A Spoonful of Hugo
+ author: Alison Hill
+ description: |
+ A forking fun new feature for series.
+ Even this sidebar offers a ton of customizations!
+
+ Check out the _index.md file in the /blog/spoonful-series
+ folder to edit this content.
+ text_link_label: ""
+ text_link_url: ""
+ show_sidebar_adunit: false # show ad container
+
+# set up common front matter for all individual pages in series
+cascade:
+ layout: single-series # for a series, do not change
+ series: A Spoonful of Hugo # name your series
+ author: Alison Hill
+ show_author_byline: true
+ show_post_date: true
+ sidebar:
+ text_link_label: ""
+ text_link_url: ""
+ show_sidebar_adunit: false # show ad container
+ text_series_label: "In this series"
+ text_contents_label: "On this page"
+ tags:
+ - hugo-site
+ categories:
+ - Theme Features
+ - R
+---
+
+** No content below YAML for the series _index. This file is a leaf bundle, and provides settings for the listing page layout and sidebar content.**
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/blog/spoonful-series/sidebar-featured.jpg b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/sidebar-featured.jpg
new file mode 100644
index 0000000..b5b5186
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/blog/spoonful-series/sidebar-featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/_index.md b/themes/hugo-apero/exampleSite/content/collection/_index.md
new file mode 100644
index 0000000..4a19b9a
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/_index.md
@@ -0,0 +1,33 @@
+---
+title: "Create a Collection"
+subtitle: "A collection, minus the blog."
+description: |
+ Sometimes you want a souped-up series- a bundle of related pages
+ meant to be read in sequence. This section is like a blog series,
+ minus the blog.
+author: Alison Hill
+show_post_thumbnail: true
+thumbnail_left: false # for list-sidebar only
+show_author_byline: false
+show_post_date: false
+# for listing page layout
+layout: list-sidebar # list, list-sidebar
+
+# set up common front matter for all individual pages in series
+cascade:
+ layout: single-series
+ sidebar:
+ title: "Create a Collection"
+ author: Alison Hill
+ description: |
+ Sometimes you want a souped-up series- a bundle of related pages
+ meant to be read in sequence. This section is like a blog series,
+ minus the blog.
+ show_author_byline: true
+ show_post_date: true
+ text_link_label: ""
+ text_link_url: ""
+ show_sidebar_adunit: true # show ad container, first page only
+ text_series_label: "Outline"
+ text_contents_label: "On this page"
+---
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/01-github/index.md b/themes/hugo-apero/exampleSite/content/collection/day01/01-github/index.md
new file mode 100644
index 0000000..0de9bc1
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day01/01-github/index.md
@@ -0,0 +1,31 @@
+---
+title: "A GitHub profile"
+weight: 1
+subtitle: "Put your best foot forward, first."
+excerpt: "You can share information about yourself with the community on GitHub by creating a profile README. GitHub shows your profile README at the top of your profile page."
+date: 2021-01-01
+draft: false
+links:
+- icon: door-open
+ icon_pack: fas
+ name: website
+ url: https://bakeoff.netlify.com/
+- icon: github
+ icon_pack: fab
+ name: code
+ url: https://github.com/apreshill/bakeoff
+---
+
+## Profile
+
+https://docs.github.com/en/github/setting-up-and-managing-your-github-profile/personalizing-your-profile
+
+## Pin projects to profile
+
+https://docs.github.com/en/github/setting-up-and-managing-your-github-profile/pinning-items-to-your-profile
+
+## Profile README
+
+This is new! Let's do it:
+
+https://docs.github.com/en/github/setting-up-and-managing-your-github-profile/managing-your-profile-readme
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/02-postcards/index.md b/themes/hugo-apero/exampleSite/content/collection/day01/02-postcards/index.md
new file mode 100644
index 0000000..96394c5
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day01/02-postcards/index.md
@@ -0,0 +1,135 @@
+---
+title: "A postcard"
+weight: 2
+subtitle: "Write and send a single postcard."
+excerpt: "In this block, we'll use the postcards package to make a single 'about' home page with only R Markdown."
+date: 2021-01-02
+---
+
+## Pre-requisites
+
+First, make sure you have the latest version of the postcards package installed from CRAN:
+
+```
+install.packages("postcards")
+```
+
+Restart your R session. If you use RStudio, use the menu item *Session > Restart R* or the associated keyboard shortcut:
+
++ Ctrl + Shift + F10 (Windows and Linux) or
++ Command + Shift + F10 (Mac OS).
+
+```
+packageVersion("postcards")
+[1] ‘0.2.0’
+```
+
+## Create GitHub repo
+
+Online.
+
+## Clone GitHub repo
+
+```
+usethis::create_from_github("https://github.com/apreshill/global-postcard.git")
+```
+
+:sparkles: Commit & Push! :sparkles:
+
+You should be committing these files:
+
++ `*.Rproj`
+
++ `.gitignore`
+
+## Create a postcard {#templates}
+
+Inside your current postcards project, use the R console:
+
+```
+library(postcards)
+```
+
+Then you could run (wait- don't do this yet!):
+
+```
+create_postcard()
+```
+
+But you could also pick one of four templates:
+
+1. `"jolla"` () [the default]
+
+1. `"jolla-blue"` ()
+
+1. `"trestles"` ()
+
+1. `"onofre"` ()
+
+```
+create_postcard(template = "jolla") #default
+create_postcard(template = "jolla-blue")
+create_postcard(template = "trestles")
+create_postcard(template = "onofre")
+```
+
+
+
+## Anatomy of a postcard
+
+YAML, body, name is index- this is special
+
+:sparkles: Commit & Push! :sparkles:
+
+You should be committing these files:
+
++ `index.Rmd`
+
++ `*.jpg`
+
+But! There is no `.html` file (yet...)
+
+
+## Knit the postcard
+
+Knit button or
+
+```
+rmarkdown::render("index.Rmd")
+```
+
+What is new in your Git pane?
+
+:sparkles: Commit & Push! :sparkles:
+
+You should be committing this files:
+
++ `index.html`
+
+(You may get a warning in RStudio IDE that this file is too big- go right ahead)
+
+## Publish a postcard
+
+Easy:
+
++ Push, publish to GitHub pages
+https://docs.github.com/en/github/working-with-github-pages/creating-a-github-pages-site#creating-your-site
+
+Medium:
+
+```
+> use_github_pages(branch = "main", path = "/")
+✓ Setting active project to '/Users/alison/rscratch/global-postcard'
+✓ Activating GitHub Pages for 'apreshill/global-postcard'
+✓ GitHub Pages is publishing from:
+● URL: 'https://apreshill.github.io/global-postcard/'
+● Branch: 'main'
+● Path: '/'
+```
+
+## Share your postcard!
+
+Add it to your repository details
+
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/index.md b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/index.md
new file mode 100644
index 0000000..05010d5
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/index.md
@@ -0,0 +1,138 @@
+---
+title: "A distill site"
+weight: 3
+subtitle: "Using the distill & postcards packages to build a personal website with R Markdown."
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-02
+draft: false
+---
+
+## Pre-requisites
+
+First, make sure you have the latest version of the distill package installed from CRAN:
+
+ install.packages("distill")
+
+Restart your R session. If you use RStudio, use the menu item *Session \> Restart R* or the associated keyboard shortcut:
+
+- Ctrl + Shift + F10 (Windows and Linux) or
+- Command + Shift + F10 (Mac OS).
+
+```{=html}
+
+```
+ packageVersion("distill")
+ [1] ‘1.2’
+
+## Create GitHub repo
+
+Online.
+
+## Clone GitHub repo
+
+ usethis::create_from_github("https://github.com/apreshill/global-distill.git")
+
+:sparkles: Commit & Push! :sparkles:
+
+You should be committing these files:
+
+- `*.Rproj`
+
+- `.gitignore`
+
+## Create a new distill site
+
+Inside your current distill project, use the R console:
+
+ library(distill)
+
+Let's start with a simple website:
+
+ create_website(dir = ".", title = "global-distill", gh_pages = TRUE)
+
+Now, let's commit all these new files and push to GitHub.
+
+## Build site
+
+Please *close* the RStudio IDE and re-open it. Look in your Git pane, you should see a single file has changed:
+
+
+
+
+
+
+
+Let's look at the diff:
+
+
+
+
+
+
+
+Let's go ahead and commit this file before we start adding to our site.
+
+You should see:
+
+![RStudio build site tab](https://rstudio-education.github.io/sharing-short-notice/images/screenshots/build-site.png)
+
+## Add a postcard
+
+Docs:
+
+Now, delete your `about.Rmd` (trust me!). We'll create a new one with the postcards package.
+
+```
+create_article(file = "about", # future name of .Rmd file
+ template = "jolla", # name of template
+ package = "postcards")
+```
+
+[Reminder: templates]({{< ref "/02-postcards#templates" >}} "Postcards templates")
+
+
+## Site navigation
+
+`_site.yml`
+
+## Theme
+
+Docs:
+
+ distill::create_theme("apreshill")
+
+Remember your `_site.yml` file? Add the theme line there:
+
+``` {.yaml}
+name: "Alison Hill"
+title: "Personal website of Dr. Alison Hill"
+description: |
+ This is my personal website.
+output_dir: "docs"
+theme: apreshill.css
+navbar:
+ right:
+ - text: "Home"
+ href: index.html
+ - text: "About"
+ href: about.html
+output: distill::distill_article
+```
+
+## Publish a distill site
+
+Easy:
+
+- Push, publish to GitHub pages
+
+Medium:
+
+```
+> use_github_pages(branch = "main", path = "/docs")
+✓ Setting active project to '/Users/alison/rscratch/global-distill'
+✓ Activating GitHub Pages for 'apreshill/global-distill'
+✓ GitHub Pages is publishing from:
+● URL: 'https://apreshill.github.io/global-distill/'
+● Branch: 'main'
+● Path: '/docs'
+```
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-diff.png b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-diff.png
new file mode 100644
index 0000000..58e5107
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-diff.png differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-git.png b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-git.png
new file mode 100644
index 0000000..0f94fe0
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/day01/03-distill/rproj-git.png differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/_index.md b/themes/hugo-apero/exampleSite/content/collection/day01/_index.md
new file mode 100644
index 0000000..47de850
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day01/_index.md
@@ -0,0 +1,19 @@
+---
+title: "Day 01"
+# list or single layouts are possible
+layout: single-series # list, list-sidebar, single-series
+show_post_thumbnail: true
+weight: 2
+publishDate: 2021-01-22
+date: 2021-01-25
+subtitle: "All about Day 01 of 'Introduce Yourself Online'."
+description: |
+ Our first day together is all about building and publishing.
+excerpt:
+author: Alison Hill
+show_post_thumbnail: true
+show_author_byline: false
+show_post_date: false
+---
+
+If you choose `layout: single-series`, you can add markdown text here and it will be the landing page for this nested subsection.
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/collection/day01/featured.jpg b/themes/hugo-apero/exampleSite/content/collection/day01/featured.jpg
new file mode 100644
index 0000000..90a176e
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/day01/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/day02/01-netlify/index.md b/themes/hugo-apero/exampleSite/content/collection/day02/01-netlify/index.md
new file mode 100644
index 0000000..71c1381
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day02/01-netlify/index.md
@@ -0,0 +1,15 @@
+---
+title: "Netlify"
+weight: 1
+subtitle: "Using Netlify to deploy."
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-02
+draft: false
+---
+
+
+So far, we've been leveraging GitHub Pages for publishing. This works great, but for blogdown we'll start using Netlify. Let's start *RIGHT NOW* with a site we've already built and published.
+
+## Pre-requisites
+
+Pick either your postcards site, or your distill site from day 01. Refresh your memory- which repository was it again?
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/collection/day02/02-blogdown/index.md b/themes/hugo-apero/exampleSite/content/collection/day02/02-blogdown/index.md
new file mode 100644
index 0000000..70fdf96
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day02/02-blogdown/index.md
@@ -0,0 +1,66 @@
+---
+title: "Using blogdown"
+weight: 2
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-01
+---
+
+
+## Pre-requisites
+
+First, make sure you have the latest version of the blogdown package installed from CRAN:
+
+```
+install.packages("blogdoown")
+```
+
+Restart your R session. If you use RStudio, use the menu item *Session > Restart R* or the associated keyboard shortcut:
+
++ Ctrl + Shift + F10 (Windows and Linux) or
++ Command + Shift + F10 (Mac OS).
+
+```
+packageVersion("blogdown")
+[1] ‘1.0’
+```
+
+## Create GitHub repo
+
+Online.
+
+## Clone GitHub repo
+
+```
+usethis::create_from_github("https://github.com/apreshill/global-blogdown.git")
+```
+
+:sparkles: Commit & Push! :sparkles:
+
+You should be committing these files:
+
++ `*.Rproj`
+
++ `.gitignore`
+
+## Create a new blogdown site
+
+We'll be using a new Hugo theme that I made for us!
+
+Inside your current blogdown project, use the R console:
+
+```
+library(blogdown)
+```
+
+Let's start with making the website with the theme:
+
+```
+new_site(dir = ".", theme = "apreshill/blogophonic")
+```
+
+## Configure your site
+
+The first stop on this tour of your site is the `config.yaml` file.
+
+
diff --git a/themes/hugo-apero/exampleSite/content/collection/day02/03-blogdown/index.md b/themes/hugo-apero/exampleSite/content/collection/day02/03-blogdown/index.md
new file mode 100644
index 0000000..2bfecc5
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day02/03-blogdown/index.md
@@ -0,0 +1,24 @@
+---
+title: "Warm woolen mittens"
+layout: single-series
+weight: 3
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2021-01-02
+draft: false
+---
+
+{{< here >}}
+
+
+## part 2!
+
+### does this work?
+
+---
+
+## now for some very cool things
+
+## more
+
+## get ready!
diff --git a/themes/hugo-apero/exampleSite/content/collection/day02/_index.md b/themes/hugo-apero/exampleSite/content/collection/day02/_index.md
new file mode 100644
index 0000000..1f4ddb4
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/day02/_index.md
@@ -0,0 +1,19 @@
+---
+title: "Day 02"
+# list or single layouts are possible
+layout: single-series # list, list-sidebar, single-series
+show_post_thumbnail: true
+weight: 3
+publishDate: 2021-01-22
+date: 2021-01-26
+subtitle: "All about Day 02 of 'Introduce Yourself Online'."
+description: |
+ day two
+excerpt:
+author: Alison Hill
+show_post_thumbnail: true
+show_author_byline: false
+show_post_date: false
+---
+
+If you choose `layout: single-series`, you can add markdown text here and it will be the landing page for this nested subsection.
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/collection/day02/featured.jpg b/themes/hugo-apero/exampleSite/content/collection/day02/featured.jpg
new file mode 100644
index 0000000..bb4000d
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/day02/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/featured-sidebar.jpg b/themes/hugo-apero/exampleSite/content/collection/featured-sidebar.jpg
new file mode 100644
index 0000000..d86cd87
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/featured-sidebar.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/prework/featured.jpg b/themes/hugo-apero/exampleSite/content/collection/prework/featured.jpg
new file mode 100644
index 0000000..e4decfa
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/collection/prework/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/collection/prework/index.md b/themes/hugo-apero/exampleSite/content/collection/prework/index.md
new file mode 100644
index 0000000..5672a51
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/collection/prework/index.md
@@ -0,0 +1,71 @@
+---
+title: "Prework"
+weight: 1
+subtitle: ""
+excerpt: "How to prepare ahead of time."
+date: 2021-01-01
+draft: false
+---
+
+Welcome to the [Introducing Yourself Online](/) workshop! We look forward to meeting you. Before attending the workshop, please complete the following prework.
+
+## Set up RStudio Cloud
+
+Sign up for a free RStudio Cloud account at https://rstudio.cloud/ before the workshop. I recommend logging in with an existing Google or GitHub account, if you have one (rather than creating a new account with another password you have to remember). I want you to be able to work from your own laptop in this workshop, but Cloud is an important back-up plan should you run into troubles.
+
+## Set up GitHub
+
+We will be using GitHub in this workshop for version control and publishing. Sign up for a free GitHub.com account at if you don't already have one. Also:
+
++ Complete these [installation instructions](https://happygitwithr.com/install-intro.html).
+
++ Test your connection between GitHub and RStudio following [these steps](https://happygitwithr.com/connect-intro.html).
+
++ **NOTE:** We *strongly recommend* that if you are not already a fluent GitHub user you choose [HTTPS over SSH](https://happygitwithr.com/credential-caching.html).
+
+## Brush up on markdown
+
+Please complete this [10-minute interactive tutorial on Markdown](https://commonmark.org/help/tutorial/).
+
+## Installations
+
+Please bring a laptop that has the following installed:
+
++ A recent version of R (>=3.6.0), which is available for free at https://cloud.r-project.org/
+
++ A recent version of RStudio Desktop (>=1.4), available for free ([RStudio Desktop Open Source License](https://www.rstudio.com/products/rstudio/download/#download)). Read up on the latest version [here](https://blog.rstudio.com/2021/01/19/announcing-rstudio-1-4/).
+
++ The R packages we will use, which you can install by connecting to the internet, opening RStudio, and running at the command line:
+
+ ```r
+ > install.packages(c("usethis", "remotes", "distill",
+ "postcards", "blogdown"))
+ ```
+
+ You'll also need to install the development version of the `rmarkdown` package:
+
+ ```r
+ > remotes::install_github("rmarkdown")
+ ```
+
+## Install Hugo
+
+To use blogdown, please install Hugo:
+```r
+> blogdown::install_hugo()
+```
+
+And ensure your current version is at least as high as:
+```r
+> hugo_version()
+[1] ‘0.79.0’
+```
+
+## Check pandoc
+
+The RStudio IDE bundles an updated version of pandoc- if you did install v1.4 of the IDE, you should be all set!
+
+```r
+> rmarkdown::pandoc_version()
+[1] ‘2.11.3’
+```
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/contributors.md b/themes/hugo-apero/exampleSite/content/contributors.md
new file mode 100644
index 0000000..d57439e
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/contributors.md
@@ -0,0 +1,27 @@
+---
+description: "Thank you to all the contributors!"
+draft: false
+layout: standard
+show_title_as_headline: true
+title: Contributors
+---
+
+Thank you to all the folks who have contributed both technical and creative skills to this project:
+
++ [Desirée De Leon :giraffe:](http://desiree.rbind.io/) (designed 5 of the custom color themes, made illustrations for the workshop, and provided general aesthetic feedback along the way)
+
++ [Garrick Aden-Buie :mage:](https://www.garrickadenbuie.com/) (debugged headroom.js and lent his panelset.js code to the theme)
+
++ [Allison Horst :dog2:](https://www.allisonhorst.com/) (awesome illustrations of campfires, seedlings, and evergreens, as well as my R Markdown hedgehog mascot :hedgehog:)
+
++ [Maëlle Salmon :fishing_pole_and_fish:](https://masalmon.eu/) (help with features, and naming the theme [Hugo Apéro](https://hugo-apero.netlify.app/)!)
+
++ [Christophe Dervieux :crayon:](http://cderv.rbind.io/) (thinking through blogdown/Hugo intricacies and syntax highlighting)
+
++ [Yihui Xie :martial_arts_uniform:](https://yihui.org/) (for the blogdown package, getting me hooked on Hugo, and helping me with layout code inspired by his many Hugo themes)
+
++ [Athanasia Monika Mowinckel :purple_heart:](https://drmowinckels.io/) (for help finding :bug: and SASS support for making color themes work so much better :art:)
+
++ [Jannik Buhr :otter:](https://jmbuhr.de) (enabling math rendering with mathjax and katex)
+
+And last but not least, Eric Anderson and the team at [Formspree](https://formspree.io/) for developing a Hugo theme with such great bones:
diff --git a/themes/hugo-apero/exampleSite/content/elements/index.html b/themes/hugo-apero/exampleSite/content/elements/index.html
new file mode 100644
index 0000000..2ef109a
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/elements/index.html
@@ -0,0 +1,162 @@
+---
+title: Typography Styles & Element Examples
+description: The "kitchen sink," if you will ... a page showing examples of type and page elements included in this template.
+date: 2019-02-18T12:27:33-06:00
+draft: false
+# layout options are standard (default) or wide-body
+layout: wide-body
+show_title_as_headline: true
+---
+
+
+
+
Font Sizes
+
+
+
+
+
A
+
A
+
A
+
A
+
A
+
A
+
A
+
A
+
+
+
6rem (96px)
+
5rem (80px)
+
3rem (48px)
+
2.25rem (36px)
+
1.5rem (24px)
+
1.25rem (20px)
+
1rem (16px)
+
.875rem (14px)
+
+
+
+
+
Type Samples
+
Headline
+
Subheadline
+
Level 1 Heading
+
One page to rule them all...well, not really. This page displays sample typography and page elements to illustrate their style. Things like headings and paragraphs showing the beautiful type scale, form elements, tabular data, and image layouts just to name a few.
+
Level 2 Heading
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla tortor mauris condimentum nibh.
+
Maecenas faucibus mollis interdum. Vestibulum id ligula porta felis euismod semper. Aenean lacinia bibendum nulla sed consectetur. Cras mattis consectetur purus sit amet fermentum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Maecenas sed diam eget risus varius blandit sit amet.
+
Level 3 Heading
+
Cras mattis consectetur purus sit amet fermentum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Fusce dapibus, tellus ac cursus commodo.
+
Level 4 Heading
+
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Nullam id dolor id nibh ultricies vehicula ut id elit. Aenean lacinia bibendum nulla sed consectetur.
+
More Type Samples
+
+
Discipline in typography is a prime virtue. Individuality must be secured by means that are rational. Distinction needs to be won by simplicity and restraint. It is equally true that these qualities need to be infused wiht a certain spirit and vitality, or they degenerate into dullness and mediocrity.
+ {{< figure src="https://via.placeholder.com/1024x768/DDD/EEE?text=4:3" alt="A sample 4:3 ratio image" caption="This is an image caption provided through a figure shortcode using figcaption." >}}
+
+
diff --git a/themes/hugo-apero/exampleSite/content/form/contact.md b/themes/hugo-apero/exampleSite/content/form/contact.md
new file mode 100644
index 0000000..c2a91ff
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/form/contact.md
@@ -0,0 +1,22 @@
+---
+title: Contact
+name: Contact Us Form
+description: "This template has a **contact-us** form built right in. All you need to do is add a valid recipient form-id to the front matter of this form page and you're ready to receive submissions."
+date: 2019-02-25T13:38:41-06:00
+draft: false
+url: contact
+type: form
+layout: split-right # split-right or split-left
+submit_button_label: Send Message
+show_social_links: true # specify social accounts in site config
+show_poweredby_formspree: true
+# From the Integration tab in Formspree where it says Your form's endpoint is:
+# https://formspree.io/f/abcdefgh The id will be "abcdefgh""
+formspree_form_id: "id-from-formspree"
+---
+
+** Contact page don't contain a body, just the front matter above.
+See form.html in the layouts folder.
+
+Formspree requires a (free) account and new form to be set up. The link is made on the final published url in the field: Restrict to Domain. It is possible to register up to 2 emails free and you can select which one you want the forms to go to within Formspree in the Settings tab.
+**
diff --git a/themes/hugo-apero/exampleSite/content/license.md b/themes/hugo-apero/exampleSite/content/license.md
new file mode 100644
index 0000000..3a3f4fc
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/license.md
@@ -0,0 +1,14 @@
+---
+title: "License"
+description: The "kitchen sink," if you will ... a page showing examples of type and page elements included in this template.
+draft: false
+# layout options are standard (default) or wide-body
+layout: standard
+show_title_as_headline: true
+---
+
+My [blog posts](/post/) are released under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
+
+
+
+
\ No newline at end of file
diff --git a/themes/hugo-apero/exampleSite/content/project/_index.md b/themes/hugo-apero/exampleSite/content/project/_index.md
new file mode 100644
index 0000000..f2c71c9
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/project/_index.md
@@ -0,0 +1,35 @@
+---
+title: A Project Portfolio To Grow
+description: "Give your projects a place to live online."
+author: "The R Markdown Team @RStudio"
+show_post_thumbnail: true
+show_author_byline: true
+show_post_date: false
+# for listing page layout
+layout: list-grid # list, list-sidebar, list-grid
+
+# for list-sidebar layout
+sidebar:
+ title: A Sidebar for Your Projects
+ description: |
+ Projects can be anything!
+ Check out the _index.md file in the /project folder
+ to edit this content.
+ author: "The R Markdown Team @RStudio"
+ text_link_label: ""
+ text_link_url: ""
+ show_sidebar_adunit: false # show ad container
+
+# set up common front matter for all individual pages inside project/
+cascade:
+ show_author_byline: true
+ show_post_date: true
+ show_comments: false # see site config to choose Disqus or Utterances
+ # for single-sidebar layout only
+ sidebar:
+ text_link_label: View all projects
+ text_link_url: /project/
+ show_sidebar_adunit: true # show ad container
+---
+
+** No content for the project index. This file provides front matter for the blog including the layout and boolean options. **
diff --git a/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-screenshot.png b/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-screenshot.png
new file mode 100644
index 0000000..1b74fe7
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-screenshot.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-thumbnail.png b/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-thumbnail.png
new file mode 100644
index 0000000..9469b9d
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/bakeoff/built-in-contact-form-thumbnail.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/bakeoff/featured-hex.png b/themes/hugo-apero/exampleSite/content/project/bakeoff/featured-hex.png
new file mode 100644
index 0000000..d00d742
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/bakeoff/featured-hex.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/bakeoff/formspree-logo.png b/themes/hugo-apero/exampleSite/content/project/bakeoff/formspree-logo.png
new file mode 100644
index 0000000..6b42767
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/bakeoff/formspree-logo.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/bakeoff/index.md b/themes/hugo-apero/exampleSite/content/project/bakeoff/index.md
new file mode 100644
index 0000000..8df1d29
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/project/bakeoff/index.md
@@ -0,0 +1,64 @@
+---
+title: "Bakeoff"
+subtitle: "An R Package"
+excerpt: "This theme has a form-to-email feature built in, thanks to the simple Formspree integration. All you need to activate the form is a valid recipient email address saved in the form front matter."
+date: 2019-07-01
+author: "Eric Anderson"
+draft: false
+tags:
+ - hugo-site
+categories:
+ - Theme Features
+ - R
+ - package
+layout: single
+links:
+- icon: door-open
+ icon_pack: fas
+ name: website
+ url: https://bakeoff.netlify.com/
+- icon: github
+ icon_pack: fab
+ name: code
+ url: https://github.com/apreshill/bakeoff
+---
+
+![Formspree Logo](formspree-logo.png)
+
+## [Formspree](https://formspree.io) makes it easy to receive submissions from HTML forms on your static website.
+
+---
+
+### Functional Form
+
+This theme has a **form-to-email** feature built in, thanks to the simple Formspree integration. All you need to activate the form is a valid recipient email address saved in the front matter of the form
+(`/content/forms/contact.md`). Of course, the example shown below (`your@email.here`) must not be used. Please use your actual email address.
+
+```toml
+# please replace with a valid Formspree form id or email address
+formspree_form_id: your@email.here
+```
+
+Update that file and you're ready to begin receiving submissions. Just submit
+the active form for the first time, and complete the email address verification
+step with Formspree, and your contact form is live. The next time someone
+fills it out, the submission will land in your inbox.
+
+### Multiple Layouts
+
+The files included with the theme have a contact page ready for copy/paste, or
+you can type `hugo new forms/contact.md` and you're off to the races. There are two
+layouts for `forms` – `split-right`, and `split-left` – you guessed it, one puts
+the form on the right and the other on the left. You just fill out the front
+matter, and the rest is automatic.
+
+```toml
+# layout options: split-right or split-left
+layout: split-right
+```
+
+![Contact Form Split Right Layout Screenshot](built-in-contact-form-screenshot.png)
+
+Both layouts display the page title and description opposite the form, and you
+can also choose to show your social icon links if you have those configured in
+the `config.toml` file.
diff --git a/themes/hugo-apero/exampleSite/content/project/giraffes/featured-hex.png b/themes/hugo-apero/exampleSite/content/project/giraffes/featured-hex.png
new file mode 100644
index 0000000..30b53d3
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/giraffes/featured-hex.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/giraffes/index.md b/themes/hugo-apero/exampleSite/content/project/giraffes/index.md
new file mode 100644
index 0000000..73eaa8b
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/project/giraffes/index.md
@@ -0,0 +1,125 @@
+---
+title: "Tachyons for Style"
+subtitle: "A tachyon /ˈtæki.ɒn/ or tachyonic particle is a hypothetical particle that always moves faster than light."
+excerpt: "Building this static site generator theme was the first time I used an Atomic (or Functional) CSS system like Tachyons. It’s a design system that provides very small (which means fast) CSS modules that you can use in your HTML."
+date: 2019-07-03
+author: "Eric Anderson"
+draft: false
+tags:
+ - hugo-site
+categories:
+ - Theme Features
+ - R
+ - package
+# layout options: single or single-sidebar
+layout: single
+---
+
+![Tachyons Logo Script](tachyons-logo-script.png)
+
+## [Tachyons](http://tachyons.io) is a design system that allows you to design gorgeous interfaces in the browser with little effort.
+
+---
+
+### Because Speed
+
+Building this static site generator theme was the first time I used an Atomic
+(or Functional) CSS system like Tachyons. It's a design system that provides
+very small (which means fast) CSS modules that you can use in your HTML. So,
+rather than writing every line of CSS, you apply the style you need as you write
+your HTML with easy to understand shorthand class names. This makes for a very
+powerful way to style, in the browser, or while building a static site like this
+one – since you can see every change with every save. **It's a joy to use.**
+
+In using this theme for your next static website project, you won't need to know
+anything about Tachyons ... so, don't freak out. Even though I used it to style
+the theme, you won't need to change a thing. BUT, if you do want to play around
+with it, you can make massive changes very easily. Just familiarize yourself
+with the [clear documentation on the design system](http://tachyons.io/docs/).
+Once you dive in, you'll recognize all the classes I'm using in the markup.
+
+### BYOTachyons
+
+One of the best features of Tachyons is the exhaustive [component
+library](https://www.tachyonstemplates.com/components/?selectedKind=AboutPages&selectedStory=AboutUs&full=0&down=0&left=1&panelRight=0)
+contributed by the community. All those components are built to work with the
+Tachyons classes, so they will work in this theme too! You can copy/paste
+components in order to quickly block out a page, then fill in your content.
+
+### Taste the Rainbow
+
+We've leveraged the [accessible color
+combinations](http://tachyons.io/docs/themes/skins/) included with Tachyons to
+offer an easy way for you to setup your site using your favorite colors. In the
+site configuration file (`config.toml`), there is a full set of color parameters
+giving you control over the theme color scheme. For an option like `siteBgColor`
+for example, you can just type one of the predefined color names from Tachyons
+and save the file. You can totally customize the theme colors within minutes of
+installing the theme.
+
+```toml
+# basic color options: use only color names as shown in the
+# "Color Palette" section of http://tachyons.io/docs/themes/skins/
+siteBgColor = "near-white"
+sidebarBgColor = "light-gray"
+headingColor = "black"
+textColor = "dark-gray"
+sidebarTextColor = "mid-gray"
+bodyLinkColor = "blue"
+navLinkColor = "near-black"
+sidebarLinkColor = "near-black"
+footerTextColor = "silver"
+buttonTextColor = "near-white"
+buttonBgColor = "black"
+buttonHoverTextColor = "white"
+buttonHoverBgColor = "blue"
+borderColor = "moon-gray"
+```
+
+### Dig Deeper
+
+Let's say you have a style guide to follow and `washed-blue` just won't cut the
+mustard. We built Blogophonic for you, too. There is a bypass of these
+predefined colors built in, you just need to dig a little deeper. In the theme
+assets, locate and open the main SCSS file (`/assets/main.scss`). After the
+crazy looking variables you probably don't recognize and directly following the
+Tachyons import (`@import 'tachyons';`) you'll see a comment that looks just
+like this:
+
+```scss
+// uncomment the import below to activate custom-colors
+// add your own colors at the top of the imported file
+// @import 'custom-colors';
+```
+
+Once you uncomment the `custom-colors` import, it will look like this:
+
+```scss
+// uncomment the import below to activate custom-colors
+// add your own colors at the top of the imported file
+@import "custom-colors";
+```
+
+Save that change, and now the color options in the `config.toml` are no longer
+active – they've been bypassed. To customize the colors, locate and open the
+`custom-colors` file found in the theme assets (`/assets/custom-colors.scss`).
+At the top of that file, you'll find a whole new set of variables for all the
+same color options, but this time you get to assign your own HEX codes.
+
+```scss
+// set your custom colors here
+$siteBgColorCustom: #e3e3da;
+$sidebarBgColorCustom: #dbdbd2;
+$textColorCustom: #666260;
+$sidebarTextColorCustom: #666260;
+$headingColorCustom: #103742;
+$bodyLinkColorCustom: #c4001a;
+$navLinkColorCustom: #c4001a;
+$sidebarLinkColorCustom: #c4001a;
+$footerTextColorCustom: #918f8d;
+$buttonTextColorCustom: #f7f7f4;
+$buttonHoverTextColorCustom: #f9f9f8;
+$buttonBgColorCustom: #103742;
+$buttonHoverBgColorCustom: #c4001a;
+$borderColorCustom: #c4beb9;
+```
diff --git a/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-logo-script.png b/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-logo-script.png
new file mode 100644
index 0000000..58a2645
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-logo-script.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-thumbnail.png b/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-thumbnail.png
new file mode 100644
index 0000000..c638506
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/giraffes/tachyons-thumbnail.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-cover.png b/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-cover.png
new file mode 100644
index 0000000..36e7049
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-cover.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-thumbnail.png b/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-thumbnail.png
new file mode 100644
index 0000000..4226fdc
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/penguins/css-grid-thumbnail.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/penguins/featured-hex.png b/themes/hugo-apero/exampleSite/content/project/penguins/featured-hex.png
new file mode 100644
index 0000000..4252836
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/penguins/featured-hex.png differ
diff --git a/themes/hugo-apero/exampleSite/content/project/penguins/index.md b/themes/hugo-apero/exampleSite/content/project/penguins/index.md
new file mode 100644
index 0000000..b724262
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/project/penguins/index.md
@@ -0,0 +1,68 @@
+---
+title: "Palmer Penguins"
+subtitle: ""
+excerpt: "Grid is the very first CSS module created specifically to solve the layout problems we’ve all been hacking our way around for as long as we’ve been making websites."
+date: 2019-07-02
+author: "Eric Anderson"
+featured: true
+draft: false
+tags:
+- hugo-site
+categories:
+- Theme Features
+- R
+- package
+# layout options: single or single-sidebar
+layout: single-sidebar
+links:
+- icon: door-open
+ icon_pack: fas
+ name: website
+ url: https://allisonhorst.github.io/palmerpenguins/
+- icon: github
+ icon_pack: fab
+ name: code
+ url: https://github.com/allisonhorst/palmerpenguins/
+- icon: newspaper
+ icon_pack: far
+ name: Blog post
+ url: https://education.rstudio.com/blog/2020/07/palmerpenguins-cran/
+---
+
+### “Grid is the very first CSS module created specifically to solve the layout problems we've all been hacking our way around for as long as we've been making websites.”
+
+*— [Chris House, A Complete Guide to CSS Grid Layout](http://chris.house/blog/a-complete-guide-css-grid-layout/)* [^1]
+
+---
+
+Since I began building websites in Y2K, I've lost count how many times the phrase "...there's got to be a better way to do this" has passed my lips. Most times, while fighting with floats and widths of content and sidebars or just basically trying to get something beside something else without using a stupid `TABLE`.
+
+Well, technology sure has come a long way since slicing up images to match the table-based layout that was just created in Dreamweaver. You'd be surprised (or maybe you wouldn't) how challenging the standard header, content, sidebar, footer layout could be to actually get right.
+
+{{< figure src="css-grid-cover.png" alt="Traditional right sidebar layout" caption="A visual example of the traditional right sidebar layout" >}}
+
+---
+
+### ERMAHGERD
+
+A proper grid is what we always wanted, no ... _needed_ to build websites with a solid, unbreakable structure. And that's why I used it in this theme. I call this feature a "scaffold" because none of the _content_ is laid out on this grid. Only the main _structure_: consisting of the `header`, `footer`, `main`, `aside`, and `footer`. As you can tell by this quote from the [W3C](https://www.w3.org/TR/css-grid-1/) on the candidate recommendation itself, Grid is the perfect tool for the job:
+
+> ##### CSS Grid Layout Module
+>
+> This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
+>
+> — _W3C_
+
+CSS Grid is a total game changer, IMHO. Compared to the bottomless pit of despair that is the old way, the new way of building a site structure can be done in as little as 5 lines of CSS. Of course, it always takes more than that, but not much. I mean this is really the meat of the deal:
+
+```css
+.grid-container {
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ grid-template-rows: repeat(3, auto);
+}
+```
+
+#### What an amazing time to be a web developer. Anyway, I hope you enjoy this "feature" that you'll probably never notice or even see. Maybe that's the best part of a good user interface – the hidden stuff that just works.
+
+[^1]: The original article cited here is now updated and maintained by the staff over at CSS-Tricks. Bookmark their version if you want to dive in and learn about CSS Grid: [A Complete Guide to Grid](https://css-tricks.com/snippets/css/complete-guide-grid/)
diff --git a/themes/hugo-apero/exampleSite/content/project/sidebar-listing.jpg b/themes/hugo-apero/exampleSite/content/project/sidebar-listing.jpg
new file mode 100644
index 0000000..aa153c5
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/project/sidebar-listing.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/talk/_index.md b/themes/hugo-apero/exampleSite/content/talk/_index.md
new file mode 100644
index 0000000..5b2f29a
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/talk/_index.md
@@ -0,0 +1,42 @@
+---
+title: Talks that Last
+description: |
+ This is a list for your talks, workshops, or other events with a time, date, and place.
+author: "The R Markdown Team @RStudio"
+show_post_thumbnail: true
+show_author_byline: true
+show_post_date: true
+show_post_time: true
+# for listing page layout
+layout: list # list, list-sidebar
+
+# for list-sidebar layout
+sidebar:
+ title: Talks that Last
+ description: |
+ This is a list for your talks, workshops, or
+ other events with a time, date, and place.
+ Even this sidebar offers a ton of customizations.
+
+ Check out the _index.md file in the /talk folder
+ to edit this content.
+ author: "The R Markdown Team @RStudio"
+ text_link_label: Subscribe via RSS
+ text_link_url: /talk/index.xml
+ show_sidebar_adunit: false # show ad container
+
+# set up common front matter for all pages inside blog/
+cascade:
+ author: "The R Markdown Team @RStudio"
+ show_author_byline: true
+ show_post_date: true
+ show_post_time: true
+ show_comments: false # see site config to choose Disqus or Utterances
+ # for single-sidebar layout
+ sidebar:
+ text_link_label: View recent talks
+ text_link_url: /talk/
+ show_sidebar_adunit: false # show ad container
+---
+
+** No content below YAML for the talk _index. This file provides front matter for the listing page layout and sidebar content. It is also a branch bundle, and all settings under `cascade` provide front matter for all pages inside talk/. You may still override any of these by changing them in a page's front matter.**
diff --git a/themes/hugo-apero/exampleSite/content/talk/campfire/featured.jpg b/themes/hugo-apero/exampleSite/content/talk/campfire/featured.jpg
new file mode 100644
index 0000000..f43193a
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/talk/campfire/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/talk/campfire/index.md b/themes/hugo-apero/exampleSite/content/talk/campfire/index.md
new file mode 100644
index 0000000..b440552
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/talk/campfire/index.md
@@ -0,0 +1,29 @@
+---
+title: "A campfire"
+subtitle: "Testing"
+excerpt: "Here is a talk I gave on making awesome personal websites using Hugo, blogdown, GitHub, and Netlify."
+date: 2021-01-12
+date_end: "2021-01-13"
+featured: true
+show_post_time: false
+event: "rstudio::global(2021)"
+event_url: https://global.rstudio.com
+author: "Alison Hill"
+location: "Sydney, Australia"
+draft: false
+# layout options: single, single-sidebar
+layout: single
+categories:
+- workshop
+links:
+- icon: door-open
+ icon_pack: fas
+ name: website
+ url: https://bakeoff.netlify.com/
+- icon: github
+ icon_pack: fab
+ name: code
+ url: https://github.com/apreshill/bakeoff
+---
+
+I'm really excited to give this talk! Stay tuned for video and slides.
diff --git a/themes/hugo-apero/exampleSite/content/talk/second-seedling/featured.jpg b/themes/hugo-apero/exampleSite/content/talk/second-seedling/featured.jpg
new file mode 100644
index 0000000..b319027
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/talk/second-seedling/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/talk/second-seedling/index.md b/themes/hugo-apero/exampleSite/content/talk/second-seedling/index.md
new file mode 100644
index 0000000..2365be2
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/talk/second-seedling/index.md
@@ -0,0 +1,15 @@
+---
+title: "A seedling"
+subtitle: "Testing"
+excerpt: "Yet another idea"
+date: 2021-01-01T14:15:59-06:00
+date_end: "2021-01-01T14:45:59-06:00"
+author: "Alison Hill"
+location: "Online"
+draft: false
+# layout options: single, single-sidebar
+layout: single
+categories:
+- meetup
+---
+
diff --git a/themes/hugo-apero/exampleSite/content/talk/seedling/featured.jpg b/themes/hugo-apero/exampleSite/content/talk/seedling/featured.jpg
new file mode 100644
index 0000000..b319027
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/talk/seedling/featured.jpg differ
diff --git a/themes/hugo-apero/exampleSite/content/talk/seedling/index.md b/themes/hugo-apero/exampleSite/content/talk/seedling/index.md
new file mode 100644
index 0000000..8018f98
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/content/talk/seedling/index.md
@@ -0,0 +1,15 @@
+---
+title: "A seedling"
+subtitle: "Testing"
+excerpt: "Another idea"
+date: 2020-01-13T14:15:59-06:00
+date_end: "2020-01-15T14:45:59-06:00"
+author: "Alison Hill"
+location: "Online"
+draft: false
+# layout options: single, single-sidebar
+layout: single
+categories:
+- meetup
+---
+
diff --git a/themes/hugo-apero/exampleSite/content/talk/sidebar-listing.jpg b/themes/hugo-apero/exampleSite/content/talk/sidebar-listing.jpg
new file mode 100644
index 0000000..49cc5d2
Binary files /dev/null and b/themes/hugo-apero/exampleSite/content/talk/sidebar-listing.jpg differ
diff --git a/themes/hugo-apero/exampleSite/data/ads/formspree.yaml b/themes/hugo-apero/exampleSite/data/ads/formspree.yaml
new file mode 100644
index 0000000..54873ac
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/data/ads/formspree.yaml
@@ -0,0 +1,4 @@
+title: Made by Formspree
+body: >
+ Formspree is a form backend, API and email
+ service for HTML forms. It is the simplest way to collect form submissions on your static website.
diff --git a/themes/hugo-apero/exampleSite/layouts/shortcodes/blogdown/postref.html b/themes/hugo-apero/exampleSite/layouts/shortcodes/blogdown/postref.html
new file mode 100644
index 0000000..1b33d19
--- /dev/null
+++ b/themes/hugo-apero/exampleSite/layouts/shortcodes/blogdown/postref.html
@@ -0,0 +1 @@
+{{ if eq (getenv "BLOGDOWN_POST_RELREF") "true" }}{{ .Page.RelPermalink }}{{ else }}{{ .Page.Permalink }}{{ end }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/404.html b/themes/hugo-apero/layouts/404.html
new file mode 100644
index 0000000..b6ed37c
--- /dev/null
+++ b/themes/hugo-apero/layouts/404.html
@@ -0,0 +1,8 @@
+{{ define "main" }}
+
+
+
404
+
Page not found
+
+
+{{ end }}
diff --git a/themes/hugo-apero/layouts/_default/_markup/render-heading.html b/themes/hugo-apero/layouts/_default/_markup/render-heading.html
new file mode 100644
index 0000000..d9e5925
--- /dev/null
+++ b/themes/hugo-apero/layouts/_default/_markup/render-heading.html
@@ -0,0 +1,14 @@
+
+
+
+
+{{ .Text | safeHTML }}
+
+ {{- if or (eq .Level 2) (eq .Level 3) -}}
+
+ {{- end -}}
+
+
diff --git a/themes/hugo-apero/layouts/_default/_markup/render-link.html b/themes/hugo-apero/layouts/_default/_markup/render-link.html
new file mode 100644
index 0000000..4ff0c2c
--- /dev/null
+++ b/themes/hugo-apero/layouts/_default/_markup/render-link.html
@@ -0,0 +1,2 @@
+{{/* A Hugo Markdown render hook to parse links, opening external links in new tabs. */}}
+{{ .Text | safeHTML }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/_default/baseof.html b/themes/hugo-apero/layouts/_default/baseof.html
new file mode 100644
index 0000000..c7c00c0
--- /dev/null
+++ b/themes/hugo-apero/layouts/_default/baseof.html
@@ -0,0 +1,11 @@
+
+
+ {{- partial "head.html" . -}}
+
+
+
diff --git a/themes/hugo-apero/layouts/partials/shared/post-pagination.html b/themes/hugo-apero/layouts/partials/shared/post-pagination.html
new file mode 100644
index 0000000..3d1a980
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/post-pagination.html
@@ -0,0 +1,12 @@
+
+ {{/* To show older, use next */}}
+ {{ with .NextInSection }}
+ ← {{.Title}}
+ {{ end }}
+ {{/* To show newer, use previous */}}
+ {{ with .PrevInSection }}
+ {{.Title}} →
+ {{ end }}
+
diff --git a/themes/hugo-apero/layouts/partials/shared/section-sidebar.html b/themes/hugo-apero/layouts/partials/shared/section-sidebar.html
new file mode 100644
index 0000000..b7c9cee
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/section-sidebar.html
@@ -0,0 +1,42 @@
+{{ $page := . }}
+{{ $section := $page.FirstSection }}
+
+{{ $series_toc_label := .Params.sidebar.text_series_label | default "In this series" }}
+{{ $page_toc_label := .Params.sidebar.text_contents_label | default "On this page" }}
+
+
+{{ partial "shared/sidebar/sidebar-adunit.html" .Params.sidebar }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-adunit.html b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-adunit.html
new file mode 100644
index 0000000..cc4a8fa
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-adunit.html
@@ -0,0 +1,7 @@
+{{ if .show_sidebar_adunit }}
+
+ {{ range site.Data.ads }}
+
{{ .title }}{{ .body | markdownify }}
+ {{ end }}
+
+{{ end }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-header.html b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-header.html
new file mode 100644
index 0000000..13674e4
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-header.html
@@ -0,0 +1,6 @@
+
+{{ with .Params.sidebar }}
+ {{ with .title }}
{{ . | markdownify }}
{{ end }}
+ {{ with .description }}
{{ . | markdownify }}
{{ end }}
+ {{ with .author }}
Written by {{ . | markdownify }}
{{ end }}
+{{ end }}
diff --git a/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-image.html b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-image.html
new file mode 100644
index 0000000..faed839
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-image.html
@@ -0,0 +1,15 @@
+{{ $page := . }}
+{{ $section := $page.CurrentSection }}
+
+
+{{ $branch := ($section.Resources.ByType "image").GetMatch "*sidebar*" }}
+
+{{ $leaf := ($page.Resources.ByType "image").GetMatch "*sidebar*" }}
+
+{{ $thumbnail := $leaf | default $branch }}
+
+{{ $first := (.FirstSection.Resources.ByType "image").GetMatch "*sidebar*" }}
+{{ $thumbnail := cond (eq $thumbnail nil) $first $thumbnail }}
+{{ with $thumbnail }}
+
+{{ end }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-link.html b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-link.html
new file mode 100644
index 0000000..6d96602
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/sidebar/sidebar-link.html
@@ -0,0 +1 @@
+{{ if .text_link_label }}{{ .text_link_label }}{{ end }}
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/partials/shared/social-links.html b/themes/hugo-apero/layouts/partials/shared/social-links.html
new file mode 100644
index 0000000..d064ffd
--- /dev/null
+++ b/themes/hugo-apero/layouts/partials/shared/social-links.html
@@ -0,0 +1,21 @@
+
+
+ {{ range site.Params.social }}
+ {{ $pack := or .icon_pack "fas" }}
+ {{ $pack_prefix := $pack }}
+ {{ if in (slice "fab" "fas" "far" "fal") $pack }}
+ {{ $pack_prefix = "fa" }}
+ {{ end }}
+ {{ $link := .url }}
+ {{ $scheme := (urls.Parse $link).Scheme }}
+ {{ $target := "" }}
+ {{ if not $scheme }}
+ {{ $link = .url | relLangURL }}
+ {{ else if in (slice "http" "https") $scheme }}
+ {{ $target = "target=\"_blank\" rel=\"noopener\"" }}
+ {{ end }}
+
+
+
+ {{ end }}
+
You'll want to edit this file, then re-knit to see the changes take effect in your site preview.
+
+ {{ end }}
+
+
To remove me, delete this line inside that file: {{ print "{{< here >}}" }}
+
+
+
My content section is:
+
{{ .Page.Section }}
+
+
+
+
My layout is:
+
{{ .Page.Params.layout }}
+
+
+ {{ with .Page.Resources.ByType "image" }}
+
+
Images in this page bundle:
+ {{ range . }}
+
{{ .RelPermalink }}
+ {{ end }}
+
+ {{ end }}
+
+
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/shortcodes/panel.html b/themes/hugo-apero/layouts/shortcodes/panel.html
new file mode 100644
index 0000000..aa1dfc4
--- /dev/null
+++ b/themes/hugo-apero/layouts/shortcodes/panel.html
@@ -0,0 +1,5 @@
+
+
{{ .Get "name" | markdownify | emojify }}
+
+ {{ with .Inner }}
{{ . | markdownify | emojify }}
{{ end }}
+
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/shortcodes/panelset.html b/themes/hugo-apero/layouts/shortcodes/panelset.html
new file mode 100644
index 0000000..417a8fa
--- /dev/null
+++ b/themes/hugo-apero/layouts/shortcodes/panelset.html
@@ -0,0 +1,3 @@
+
+ {{ .Inner }}
+
\ No newline at end of file
diff --git a/themes/hugo-apero/layouts/talk/list-sidebar.html b/themes/hugo-apero/layouts/talk/list-sidebar.html
new file mode 100644
index 0000000..9dd075d
--- /dev/null
+++ b/themes/hugo-apero/layouts/talk/list-sidebar.html
@@ -0,0 +1,23 @@
+{{ define "main" }}
+{{ $caller := . }}
+
+
+ {{ $caller := . }}
+ {{ $paginator := .Paginate ((where .RegularPages "Type" .Section).GroupByDate "2006") }}
+ {{ range $paginator.PageGroups }}
+
+
+