Skip to content

Commit

Permalink
Add section in functions.Rmd showing how to use fun in workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
joelnitta committed Dec 26, 2024
1 parent 2a5d737 commit f840e25
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
2 changes: 1 addition & 1 deletion episodes/cache.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Episode summary: Show how to get at the objects that we built

## Where does the workflow happen?

So we just finished running our first workflow.
So we just finished running our workflow.
Now you probably want to look at its output.
But, if we just call the name of the object (for example, `penguins_data`), we get an error.
```{r}
Expand Down
69 changes: 59 additions & 10 deletions episodes/functions.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ if (interactive()) {
source("files/lesson_functions.R")
```

## Create a function

### About functions
## About functions

Functions in R are something we are used to thinking of as something that comes from a package. You find, install and use specialized functions from packages to get your work done.

Expand All @@ -58,10 +56,11 @@ Furthermore, `targets` makes extensive use of custom functions, so a basic under
### Writing a function

There is not much difference between writing your own function and writing other code in R, you are still coding with R!
Let's imagine we want to convert the millimeter measurements in the Penguins data to centimeters.
Let's imagine we want to convert the millimeter measurements in the penguins data to centimeters.

```{r}
#| label: targets-functions-problem
#| message: FALSE
library(palmerpenguins)
library(tidyverse)
Expand Down Expand Up @@ -96,23 +95,30 @@ For our mm to cm conversion the function would look like so:
mm2cm <- function(x) {
x / 10
}
# use it
```

Our custom function will now transform any numerical input by dividing it by 10.

Let's try it out:

```{r}
#| label: targets-functions-cm-use
penguins |>
mutate(
bill_length_cm = mm2cm(bill_length_mm),
bill_depth_cm = mm2cm(bill_depth_mm)
)
```

Our custom function will now transform any numerical input by dividing it by 10.
Congratulations, you've created and used your first custom function!

### Make a function from existing code

Many times, we might already have a piece of code that we'd like to use to create a function.
For instance, we've copy-pasted a section of code several times and realize that this piece of code is repetitive, so a function is in order.
Or, you are converting your workflow to `targets`, and need to change your script into a series of functions that `targets` will call.

Recall the code snippet we had to clean our Penguins data:
Recall the code snippet we had to clean our penguins data:

```{r}
#| label: code-to-convert-to-function
Expand Down Expand Up @@ -142,6 +148,8 @@ clean_penguin_data <- function(penguins_data_raw) {
}
```

Add this function to `_targets.R` after the part where you load packages with `library()` and before the list at the end.

::::::::::::::::: callout

# RStudio function extraction
Expand Down Expand Up @@ -178,9 +186,50 @@ vecmean <- function(x) {

:::::::::::::::::::::::::::::::::::::

Congratulations, you've started a whole new journey into functions!
This was a very brief introduction to functions, and you will likely need to get more help in learning about them.
There is an episode in the R Novice lesson from Carpentries that is [all about functions](https://swcarpentry.github.io/r-novice-gapminder/10-functions.html) which you might want to read.
## Using functions in the workflow

Now that we've defined our custom data cleaning function, we can put it to use in the workflow.

Can you see how this might be done?

We need to delete the corresponding code from the last `tar_target()` and replace it with a call to the new function.

Modify the workflow to look like this:

```{r}
#| label = "targets-show-fun-add",
#| eval = FALSE,
#| code = readLines("files/plans/plan_1.R")[2:21]
```

We should run the workflow again with `tar_make()` to make sure it is up-to-date:

```{r}
#| label: targets-run-fun
#| eval: true
#| echo: [5]
pushd(make_tempdir())
write_example_plan("plan_0.R")
tar_make(reporter = "silent")
write_example_plan("plan_1.R")
tar_make()
popd()
```

We will learn more soon about the messages that `targets()` prints out.

## Functions make it easier to reason about code

Notice that now the list of targets at the end is starting to look like a high-level summary of your analysis.

This is another advantage of using custom functions: **functions allows us to separate the details of each workflow step from the overall workflow**.

To understand the overall workflow, you don't need to know all of the details about how the data were cleaned; you just need to know that there was a cleaning step.
On the other hand, if you do need to go back and delve into the specifics of the data cleaning, you only need to pay attention to what happens inside that function, and you can ignore the rest of the workflow.
**This makes it easier to reason about the code**, and will lead to fewer bugs and ultimately save you time and mental energy.

Here we have only scratched the surface of functions, and you will likely need to get more help in learning about them.
For more information, we recommend reading this episode in the R Novice lesson from Carpentries that is [all about functions](https://swcarpentry.github.io/r-novice-gapminder/10-functions.html).

::::::::::::::::::::::::::::::::::::: keypoints

Expand Down

0 comments on commit f840e25

Please sign in to comment.