Skip to content

Commit

Permalink
Fix grammar and code style
Browse files Browse the repository at this point in the history
  • Loading branch information
joelnitta committed Dec 24, 2024
1 parent 1c7ec97 commit 9d37d6d
Showing 1 changed file with 34 additions and 41 deletions.
75 changes: 34 additions & 41 deletions episodes/functions.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ source("files/lesson_functions.R")

### 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 specialised functions from packages to get your work done.
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.

But you can, and arguable should, be writing your own functions too!
Functions are a great way of making it easy to repeat the same operation but with different scopes.
How many times have you copy + pasted the exact same code in your script, only to change a couple of things (a variable, an input etc) before running it again?
Only to then discover that there was an error in the code, and when you fix it, you need to remember to do so in all the placed you copied that code.
But you can, and arguably should, be writing your own functions too!
Functions are a great way of making it easy to repeat the same operation but with different settings.
How many times have you copy-pasted the exact same code in your script, only to change a couple of things (a variable, an input etc.) before running it again?
Only to then discover that there was an error in the code, and when you fix it, you need to remember to do so in all the places where you copied that code.

Through writing functions you can reduce this back and fort, and create a more efficient workflow for your self.
Through writing functions you can reduce this back and forth, and create a more efficient workflow for yourself.
When you find the bug, you fix it in a single place, the function you made, and each subsequent call of that function will now be fixed.

### 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.

Expand All @@ -64,22 +65,22 @@ library(tidyverse)
penguins |>
mutate(
bill_length_cm = bill_length_mm/10,
bill_depth_cm = bill_depth_mm/10
)
bill_length_cm = bill_length_mm / 10,
bill_depth_cm = bill_depth_mm / 10
)
```

This is not a complicated operation, but we might want to anyway make our selves a convenient custom function that can do this conversion for us.
This is not a complicated operation, but we might want to make a convenient custom function that can do this conversion for us anyways.

To write a function, you need to use the `function()` function.
With this function we provide what will be the input arguments of the function inside its parentheses, and what the function will subsequently do with those input arguments in curly braces `{}` after the function parentheses.
The object name we assign this to, will become the functions name.
The object name we assign this to, will become the function's name.

```{r}
#| label: targets-functions-skeleton
#| eval: false
my_function <- function(argument1, argument2){
my_function <- function(argument1, argument2) {
# the things the function will do
}
# call the function
Expand All @@ -90,107 +91,99 @@ For our mm to cm conversion the function would look like so:

```{r}
#| label: targets-functions-cm
mm2cm <- function(x){
x/10
mm2cm <- function(x) {
x / 10
}
# use it
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.


### 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 realise that this piece of code is repeating, 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.
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:

```{r}
#| label: code-to-convert-to-function
#| eval: false
penguins_data_raw |>
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)` ) |>
bill_depth_mm = `Culmen Depth (mm)`
) |>
drop_na()
```

We need to adapt this code to become a function, and this function needs a single argument, which is the dataset it should clean.

It should look like this:
```{r}
#| label: clean-data-function
clean_penguin_data <- function(penguins_data_raw) {
penguins_data_raw |>
# Rename columns for easier typing and
# subset to only the columns needed for analysis
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)`
) |>
# Delete rows with missing data
drop_na()
}
```


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

# RStudio function extraction

RStudio also has a handy helper to extract a function from a piece oyou have basic familiarity with functions, may help you figure out the main necessary input when turning code into a function.

:::::::::::::: solution

## Using the tool
RStudio also has a handy helper to extract a function from a piece of code.
Once you have basic familiarity with functions, it may help you figure out the necessary input when turning code into a function.

To use it, highlight the piece of code you want to make into a function.
In our case that is the entire pipeline from `penguins_data_raw` to the `drop_na` statement.
In our case that is the entire pipeline from `penguins_data_raw` to the `drop_na()` statement.
Once you have done this, in RStudio go to the "Code" section in the top bar, and select "Extract function" from the list.
A prompt will open asking you to n
Hit enter, and you should have the following code in your script where the cursor was.
A prompt will open asking you to hit enter, and you should have the following code in your script where the cursor was.

This function will not work, because it contains more stuff than is needed as an argument.
This function will not work however, because it contains more stuff than is needed as an argument.
This is because tidyverse uses non-standard evaluation, and we can write unquoted column names inside the `select()`.
The function extractor thinks that all unquoted text (or back-ticked) in the code is a reference to an object.
The function extractor thinks that all unquoted (or back-ticked) text in the code is a reference to an object.
You will need to do some manual cleaning to get the function working, which is why its more convenient if you have a little experience with functions already.

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

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


::::::::::::::::::::::::::::::::::::: {.challenge}

## Challenge: Write a function that takes a numerical vector and returns its mean divided by 10.

:::::::::::::::::::::::::::::::::: {.solution}

```{r}
vecmean <- function(x){
mean(x)/10
#| label: write-function-answer
vecmean <- function(x) {
mean(x) / 10
}
```

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

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


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 have a read through.
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.

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

- Functions are crucial when repeating the same code many times with minor differences
- RStudio's "Extract function" tool can help you get started with converting code into functions
- Functions are an essential part of how targets work.
- Functions are an essential part of how `targets` works.

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

0 comments on commit 9d37d6d

Please sign in to comment.