Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Geocomputation with R is a book on geographic data analysis, visualization, and modeling. Each chapter1 ends with a set of exercises allowing the readers to test how well they understand each presented concepts and approaches. However, exercises are often not enough without their solutions, which provides a way to compare readers’ answers with an expected one. This leads to technical questions: how to provide solutions to the exercises without making the book too long, and to minimise duplication of words/effort (for the questions and answers)? Also, how to test, at the same time, if the solutions are still working?
For the first edition of the book we added solutions as external set of vignettes. This approach had, however, several flaws. Most importantly, solutions in the vignettes were detached from the exercises in the book, meaning that if we decided to change an exercise, we would need to go to a different repository and update it there as well. Additionally, the solution vignettes had a different style from the book and were harder to find. We decided to try a different approach for the second edition of the book. This time, we created an external bookdown-based website for solutions, which you can find at https://geocompr.github.io/solutions/. The main goal of this blog post is to explain the new setup in some detail.
< section id="new-solutions-website" class="level2">New solutions website
Firstly, let’s take a look at the bigger picture. Exercises are shown at the end of the book chapters, for example, exercises for chapter 6 can be seen at https://geocompr.robinlovelace.net/raster-vector.html#exercises-4. You may notice that this exercises section starts with a description of prerequisites, and then several questions are listed. However, what to do when I want to find solutions to these problems or compare my results with those provided by the book authors? Then, we can visit the corresponding chapter in the solution website at https://geocompr.github.io/solutions/raster-vector.html. Note that the solution website contains the same content as the exercises section, and extends it with the solution code, code results, and newly created figures.
< section id="solutions" class="level2">Solutions
Next, let’s dive deeper to see how it works. We can look at the source code of the solution website first – https://github.com/geocompr/solutions, and solutions for chapter 6 are at https://github.com/geocompr/solutions/blob/main/06-raster-vector.Rmd. If you open the last link, you should see a code looking like that:
```{r setup, echo=FALSE, results='hide'} ex = tempfile(fileext = ".Rmd") on.exit(unlink(ex)) download.file("https://raw.githubusercontent.com/Robinlovelace/geocompr/main/_06-ex.Rmd", ex) ``` ```{r, echo=FALSE, results='asis'} res = knitr::knit_child(ex, quiet = TRUE, options = list(include = TRUE)) cat(res, sep = '\n') ```
What is going on here? In short, we have two code chunks. The first (hidden) code chunk downloads a _06-ex.Rmd
file from the Robinlovelace/geocompr
repository. Ok, but how does this _06-ex.Rmd
document looks like? You can see its content at https://raw.githubusercontent.com/Robinlovelace/geocompr/main/_06-ex.Rmd. It is a mix of text (mainly exercises questions) and R code chunks. Note here that most code chunks do not have any code chunks options set, except the first one. We wanted the first code chunk to be visible on the main book and the solution websites, so we used include = TRUE
.
The second code chunk takes the downloaded document and knits it with a new global option, include = TRUE
. This option make sure that we will show all possible outputs from _06-ex.Rmd
, including numerical results and plots.
Exercises
The above section explained how we could see exercises and solutions on the solution website. However, how is it possible that we can only see the exercise text in the book? Let’s look at the bottom of the source code of the 6th chapter at https://github.com/Robinlovelace/geocompr/blob/main/06-raster-vector.Rmd:
## Exercises ```{r, echo=FALSE, results='asis'} res = knitr::knit_child('_06-ex.Rmd', quiet = TRUE, options = list(include = FALSE, eval = FALSE)) cat(res, sep = '\n') ```
There is only one short code chunk – it knits the same document, _06-ex.Rmd
, however using different global options, include = FALSE, eval = FALSE
. This assures that the book’s readers would not see any solutions’ code chunks or their outputs.
Workflow
Now we know all of the pieces of the puzzle. The last step is to connect them together with GitHub Actions.
Our workflow is as follows:
- We add/update/modify exercises and their solutions stored in a file per chapter, e.g.,
_06-ex.Rmd
- We push the changes to the main book repository on GitHub (
Robinlovelace/geocompr
) - The book is automatically built using a GitHub Actions workflow, including exercises (but not solutions!)
- Once a week, another GitHub Actions workflow runs in the solutions repository.
This approach ensures that the solutions are always up-to-date, reproducible, and in sync. with the manuscript. It creates a resources dedicated to the exercises and their solutions, helping people learn. It should also encourage others to get involved: can you think of another exercise or an alternative solution to existing exercises? You have all the info you need to contribute now. Let us know your comments or suggestions at https://github.com/geocompr/solutions! Pull Requests are also welcome!
Footnotes
Except the last one.↩︎
Reuse
< section class="quarto-appendix-contents">Citation
@online{nowosad2022, author = {Jakub Nowosad}, title = {Automatic Website for the {Geocomputation} with {R} Solutions}, date = {2022-02-24}, url = {https://geocompx.org//post/2022/geocompr-solutions}, langid = {en} }
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.