|
1 | | ---- |
2 | | -title: "Writing our own functions" |
3 | | -teaching: 15 |
4 | | -exercises: 15 |
5 | | ---- |
6 | | - |
7 | | -::: questions |
8 | | -- "How can I add functionality to my package?" |
9 | | -::: |
10 | | - |
11 | | -::: objectives |
12 | | -- "Create a custom package" |
13 | | -::: |
14 | | - |
15 | | - |
16 | | -So far, we have been playing with the example package that is built-in in `RStudio`. |
17 | | -It only contains a function that says `Hello, world!`. |
18 | | -It is extremely useful that we have an example that gets us started, but this package is not very interesting yet. |
19 | | -In this and the next episodes, we will create our own customized package, which in the previous episode we gave the name of `mysterycoffee`. |
20 | | - |
21 | | -## `mysterycoffee`, our virtual coffee room |
22 | | - |
23 | | -Our package will try to mitigate a practical problem: social isolation in remote working environments. |
24 | | -We want to create a software solution that simulates random encounters at the office's coffee machine... when there is no office. |
25 | | -The very first step is to answer three very important questions: |
26 | | - |
27 | | -### 1. What will our package do? |
28 | | -As we said, our package will simulate random encounters between employees. |
29 | | - |
30 | | -### 2. How will we do it? |
31 | | -After some thinking, we figured out that we can have a function that has the following input and output: |
32 | | - |
33 | | -- **Input**: vector of employees' names. |
34 | | -- **Output**: a two-column matrix, randomly grouping the employees' names into couples. |
35 | | - |
36 | | -The output table can be published, say, weekly, and each couple invited to have a videoconference-coffee chat, just as if they had randomly met at the coffee machine. |
37 | | - |
38 | | -So this will be our starting point. |
39 | | -In the next sections we'll write an R function that does exactly this. |
40 | | - |
41 | | -Later on, we'll see that our original design may face unexpected challenges. |
42 | | -For instance, what happens [if the number of employees not even](https://carpentries-incubator.github.io/lesson-R-packaging/05-testing/index.html#what-to-do-if-a-test-fails)? |
43 | | - |
44 | | -### 3. Are we reinventing the wheel? |
45 | | -This is also an important question worth investing some time in when creating new functions or packages. |
46 | | -Can we solve our problem with a software solution that someone else already wrote? |
47 | | - |
48 | | -Well... if our problem really was to simulate random encounters, the answer is yes. |
49 | | -There are already solutions for this. |
50 | | -But our **real** problem is learning how to make R Packages, isn't it? |
51 | | -So we'll use this problem as a pedagogical example. |
52 | | - |
53 | | -## Getting our hands dirty |
54 | | - |
55 | | -### First step: remove `hello.R` |
56 | | -The next step is to remove the file `hello.R`. |
57 | | -This was just an example file, and we don't need it anymore. |
58 | | - |
59 | | -### Second step: edit `DESCRIPTION` |
60 | | -Now that we know what our package is expected to do, it is a perfect moment to edit the `DESCRIPTION` file. |
61 | | - |
62 | | -::: challenge |
63 | | -## The `DESCRIPTION` file |
64 | | -Open the `DESCRIPTION` file. |
65 | | -What do you see here? |
66 | | - |
67 | | -Take 5 minutes to edit this file with the information it asks. |
68 | | -In particular, edit the following fields (when needed): |
69 | | -`Title`, `Version`, `Author`, `Maintainer`, `Description`. |
70 | | -For now, ignore the rest. |
71 | | - |
72 | | -:::: solution |
73 | | -After editing, your `DESCRIPTION` file should look similar to: |
74 | | - |
75 | | -```txt |
76 | | -Package: mysterycoffee |
77 | | -Type: Package |
78 | | -Title: Simulation of random encounters between couples of persons |
79 | | -Version: 0.1.0 |
80 | | -Author: Pablo Rodriguez-Sanchez |
81 | | -Maintainer: Pablo Rodriguez-Sanchez <[email protected] |
82 | | -Description: Simulates random encounters between couples of persons |
83 | | - This package was inspired by the need to mitigate social isolation in remote |
84 | | - working environments. The idea is to simulate random encounters at the office's |
85 | | - coffee machine... when there is no such an office. |
86 | | -License: What license is it under? |
87 | | -Encoding: UTF-8 |
88 | | -LazyData: true |
89 | | -RoxygenNote: 7.1.1 |
90 | | -``` |
91 | | -:::: |
92 | | -::: |
93 | | - |
94 | | -::: callout |
95 | | -## More on `DESCRIPTION` |
96 | | -In the previous exercise we deliberately ignored some of the fields in the `DESCRIPTION` file. |
97 | | -Two of them are particularly relevant, the `Version` and the `License` fields. |
98 | | - |
99 | | -The `Version` field helps you and your users keep track of the package version. |
100 | | -It is advisable to use [_semantic versioning_](https://semver.org/). |
101 | | -In a nutshell, _semantic versioning_ means using a `MAJOR.MINOR.PATCH` structure for naming your versions. |
102 | | -If your new version only fixes some bugs, increase the `PATCH` by one. |
103 | | -If your new version includes new features, increase the `MINOR` by one. |
104 | | -If your new version includes new features that are not backwards compatible, increase `MAJOR` by one. |
105 | | - |
106 | | -Regarding the `License`: software licensing is a large and complicated field which lies at the intersection of programming and law. |
107 | | -Its intricacies are far beyond the aim of this course. |
108 | | -The good news is that, most likely, most of your research code can be released under a _permissive_ license, typically _MIT_ or _Apache_. |
109 | | -If you want to know more, please take a look at [these materials](https://r-pkgs.org/license.html#license). |
110 | | - |
111 | | -For more, detailed information about `DESCRIPTION` files, see [R Packages documentation](https://r-pkgs.org/description.html). |
112 | | -::: |
113 | | - |
114 | | -### Third step: create a function |
115 | | - |
116 | | -We came up with the following prototype function that will do the random grouping: |
117 | | - |
118 | | -```r |
119 | | -make_groups <- function(names) { |
120 | | - # Shuffle the names |
121 | | - names_shuffled <- sample(names) |
122 | | - |
123 | | - # Arrange it as a two-columns matrix |
124 | | - matrix(names_shuffled, ncol = 2) |
125 | | -} |
126 | | -``` |
127 | | - |
128 | | -Please, open an editor, copy the function above and save it as `R/functions.R`. |
129 | | -All the functions of the package have to be in `R` files inside the `R/` folder. |
130 | | - |
131 | | -::: callout |
132 | | -## On the art of being tidy |
133 | | -So far, our package only has one function, and we have chosen a very boring name for the file where it is stored (`R/functions.R`). |
134 | | - |
135 | | -In the future, keep in mind that you can use any valid filename for storing your functions. |
136 | | -Additionally, such a file can contain one or many functions, and you can use multiple files if you want. |
137 | | -Indeed, using multiple files with descriptive filenames is a good idea. |
138 | | - |
139 | | -For instance, if your package has some functions for doing input, output and parsing of data, it could be a good idea to store those as `R/io.R`. |
140 | | -You can later put your analysis functions in `R/analysis.R`, and the plotting ones under `R/plotting.R`. |
141 | | - |
142 | | -Be creative and informative! The only rule is that your `.R` files should "live" inside the `R/` folder. |
143 | | -::: |
144 | | - |
145 | | -::: keypoints |
146 | | -- "It is important to think about **what** we want our package to do (_design_) and **how** to do it (_implementation_). We also want to know **why** we need a new package (_avoid reinventing the wheel_)" |
147 | | -- "Functions have to be saved in `.R` files in the R folder" |
148 | | -::: |
| 1 | +--- |
| 2 | +title: "Writing our own functions" |
| 3 | +teaching: 15 |
| 4 | +exercises: 15 |
| 5 | +--- |
| 6 | + |
| 7 | +::: questions |
| 8 | +- "How can I add functionality to my package?" |
| 9 | +::: |
| 10 | + |
| 11 | +::: objectives |
| 12 | +- "Create a custom package" |
| 13 | +::: |
| 14 | + |
| 15 | + |
| 16 | +So far, we have been playing with the example package that is built-in in `RStudio`. |
| 17 | +It only contains a function that says `Hello, world!`. |
| 18 | +It is extremely useful that we have an example that gets us started, but this package is not very interesting yet. |
| 19 | +In this and the next episodes, we will create our own customized package, which in the previous episode we gave the name of `mysterycoffee`. |
| 20 | + |
| 21 | +## `mysterycoffee`, our virtual coffee room |
| 22 | + |
| 23 | +Our package will try to mitigate a practical problem: social isolation in remote working environments. |
| 24 | +We want to create a software solution that simulates random encounters at the office's coffee machine... when there is no office. |
| 25 | +The very first step is to answer three very important questions: |
| 26 | + |
| 27 | +### 1. What will our package do? |
| 28 | +As we said, our package will simulate random encounters between employees. |
| 29 | + |
| 30 | +### 2. How will we do it? |
| 31 | +After some thinking, we figured out that we can have a function that has the following input and output: |
| 32 | + |
| 33 | +- **Input**: vector of employees' names. |
| 34 | +- **Output**: a two-column matrix, randomly grouping the employees' names into couples. |
| 35 | + |
| 36 | +The output table can be published, say, weekly, and each couple invited to have a videoconference-coffee chat, just as if they had randomly met at the coffee machine. |
| 37 | + |
| 38 | +So this will be our starting point. |
| 39 | +In the next sections we'll write an R function that does exactly this. |
| 40 | + |
| 41 | +Later on, we'll see that our original design may face unexpected challenges. |
| 42 | +For instance, what happens [if the number of employees not even](https://carpentries-incubator.github.io/lesson-R-packaging/05-testing/index.html#what-to-do-if-a-test-fails)? |
| 43 | + |
| 44 | +### 3. Are we reinventing the wheel? |
| 45 | +This is also an important question worth investing some time in when creating new functions or packages. |
| 46 | +Can we solve our problem with a software solution that someone else already wrote? |
| 47 | + |
| 48 | +Well... if our problem really was to simulate random encounters, the answer is yes. |
| 49 | +There are already solutions for this. |
| 50 | +But our **real** problem is learning how to make R Packages, isn't it? |
| 51 | +So we'll use this problem as a pedagogical example. |
| 52 | + |
| 53 | +## Getting our hands dirty |
| 54 | + |
| 55 | +### First step: remove `hello.R` |
| 56 | +The next step is to remove the file `hello.R`. |
| 57 | +This was just an example file, and we don't need it anymore. |
| 58 | + |
| 59 | +### Second step: edit `DESCRIPTION` |
| 60 | +Now that we know what our package is expected to do, it is a perfect moment to edit the `DESCRIPTION` file. |
| 61 | + |
| 62 | +::: challenge |
| 63 | +## The `DESCRIPTION` file |
| 64 | +Open the `DESCRIPTION` file. |
| 65 | +What do you see here? |
| 66 | + |
| 67 | +Take 5 minutes to edit this file with the information it asks. |
| 68 | +In particular, edit the following fields (when needed): |
| 69 | +`Title`, `Version`, `Author`, `Maintainer`, `Description`. |
| 70 | +For now, ignore the rest. |
| 71 | + |
| 72 | +:::: solution |
| 73 | +After editing, your `DESCRIPTION` file should look similar to: |
| 74 | + |
| 75 | +```txt |
| 76 | +Package: mysterycoffee |
| 77 | +Type: Package |
| 78 | +Title: Simulation of random encounters between couples of persons |
| 79 | +Version: 0.1.0 |
| 80 | +Author: Pablo Rodriguez-Sanchez |
| 81 | +Maintainer: Pablo Rodriguez-Sanchez <[email protected] |
| 82 | +Description: Simulates random encounters between couples of persons |
| 83 | + This package was inspired by the need to mitigate social isolation in remote |
| 84 | + working environments. The idea is to simulate random encounters at the office's |
| 85 | + coffee machine... when there is no such an office. |
| 86 | +License: What license is it under? |
| 87 | +Encoding: UTF-8 |
| 88 | +LazyData: true |
| 89 | +RoxygenNote: 7.1.1 |
| 90 | +``` |
| 91 | +:::: |
| 92 | +::: |
| 93 | + |
| 94 | +::: callout |
| 95 | +## More on `DESCRIPTION` |
| 96 | +In the previous exercise we deliberately ignored some of the fields in the `DESCRIPTION` file. |
| 97 | +Two of them are particularly relevant, the `Version` and the `License` fields. |
| 98 | + |
| 99 | +The `Version` field helps you and your users keep track of the package version. |
| 100 | +It is advisable to use [_semantic versioning_](https://semver.org/). |
| 101 | +In a nutshell, _semantic versioning_ means using a `MAJOR.MINOR.PATCH` structure for naming your versions. |
| 102 | +If your new version only fixes some bugs, increase the `PATCH` by one. |
| 103 | +If your new version includes new features, increase the `MINOR` by one. |
| 104 | +If your new version includes new features that are not backwards compatible, increase `MAJOR` by one. |
| 105 | + |
| 106 | +Regarding the `License`: software licensing is a large and complicated field which lies at the intersection of programming and law. |
| 107 | +Its intricacies are far beyond the aim of this course. |
| 108 | +The good news is that, most likely, most of your research code can be released under a _permissive_ license, typically _MIT_ or _Apache_. |
| 109 | +If you want to know more, please take a look at [these materials](https://r-pkgs.org/license.html#license). |
| 110 | + |
| 111 | +For more, detailed information about `DESCRIPTION` files, see [R Packages documentation](https://r-pkgs.org/description.html). |
| 112 | +::: |
| 113 | + |
| 114 | +### Third step: create a function |
| 115 | + |
| 116 | +We came up with the following prototype function that will do the random grouping: |
| 117 | + |
| 118 | +```r |
| 119 | +make_groups <- function(names) { |
| 120 | + # Shuffle the names |
| 121 | + names_shuffled <- sample(names) |
| 122 | + |
| 123 | + # Arrange it as a two-columns matrix |
| 124 | + matrix(names_shuffled, ncol = 2) |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +Please, open an editor, copy the function above and save it as `R/functions.R`. |
| 129 | +All the functions of the package have to be in `R` files inside the `R/` folder. |
| 130 | + |
| 131 | +::: callout |
| 132 | +## On the art of being tidy |
| 133 | +So far, our package only has one function, and we have chosen a very boring name for the file where it is stored (`R/functions.R`). |
| 134 | + |
| 135 | +In the future, keep in mind that you can use any valid filename for storing your functions. |
| 136 | +Additionally, such a file can contain one or many functions, and you can use multiple files if you want. |
| 137 | +Indeed, using multiple files with descriptive filenames is a good idea. |
| 138 | + |
| 139 | +For instance, if your package has some functions for doing input, output and parsing of data, it could be a good idea to store those as `R/io.R`. |
| 140 | +You can later put your analysis functions in `R/analysis.R`, and the plotting ones under `R/plotting.R`. |
| 141 | + |
| 142 | +Be creative and informative! The only rule is that your `.R` files should "live" inside the `R/` folder. |
| 143 | +::: |
| 144 | + |
| 145 | +::: keypoints |
| 146 | +- "It is important to think about **what** we want our package to do (_design_) and **how** to do it (_implementation_). We also want to know **why** we need a new package (_avoid reinventing the wheel_)" |
| 147 | +- "Functions have to be saved in `.R` files in the R folder" |
| 148 | +::: |
0 commit comments