Skip to content

Commit 98faa3c

Browse files
Merge pull request #88 from ImperialCollegeLondon/87_fusen
[Blog] Building an R package using {fusen}
2 parents e040e25 + 244f159 commit 98faa3c

File tree

6 files changed

+240
-0
lines changed

6 files changed

+240
-0
lines changed

.wordlist.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ AlphaFold
88
Andrie
99
ArcGIS
1010
Arianna
11+
Atzert
1112
Backtesting
1213
Bhogal
1314
BlackScholesOption
@@ -16,6 +17,7 @@ Booch
1617
Bytewax
1718
CFF
1819
CPUs
20+
CRAN
1921
CSP
2022
CSV
2123
CSVY
@@ -55,6 +57,7 @@ Feregrino's
5557
Fonnesbeck
5658
Frick
5759
Fundinger
60+
Fusen
5861
Fürlich
5962
GANs
6063
GIS
@@ -225,6 +228,7 @@ formatters
225228
frac
226229
frictionless
227230
funder
231+
fusen
228232
geospatial
229233
github
230234
hackathon
@@ -252,6 +256,7 @@ nd
252256
np
253257
numpy
254258
ons
259+
param
255260
parameterisation
256261
pdfs
257262
performant

docs/posts/20250210_fusen.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
---
2+
date: 2025-02-10
3+
authors:
4+
- SaranjeetKaur
5+
categories:
6+
- Technology
7+
tags:
8+
- R
9+
- Package
10+
---
11+
12+
13+
# **Building an R package using {fusen}**
14+
15+
!["Origami" by Andy Atzert is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/?ref=openverse.](images/fusen/origami.jpg){: style="display:block;margin:auto;width:69%" }
16+
17+
Writing your first full R package can feel overwhelming and {fusen}
18+
can help support at this stage (Even if you are an experienced developer, there is something for you too in this blog. Please read on!). "Fusen" is a type of
19+
[Japanese origami](https://en.wikipedia.org/wiki/Kamif%C5%ABsen) in which
20+
a flat piece of paper, when folded in a specific way and inflated, turns
21+
into a nice paper box/balloon. Similarly, the {fusen} package inflates a
22+
flat `.Rmd` template (which is filled in a specific way) and returns a
23+
nice package. In this blog post, I am sharing my experience of
24+
exploring {fusen} for the first time.
25+
<!-- more -->
26+
27+
## Pre-requisites
28+
29+
- [RStudio installed](https://posit.co/download/rstudio-desktop/)
30+
- [Connect RStudio to Git and GitHub](https://happygitwithr.com/rstudio-git-github.html) (_Optional, but recommended_)
31+
32+
## Installation and initial setup
33+
34+
The CRAN released version of {fusen} can be installed using:
35+
36+
``` r
37+
install.packages("fusen")
38+
```
39+
40+
Then we will have to create a new new project in RStudio by following:
41+
`File > New Project > New directory > Package using {fusen}`.
42+
This will open a `Create Package using {fusen}` wizard.
43+
Specify the directory name and choose a {fusen} template to work with.
44+
If you want to see how {fusen} works then select the `teaching` template
45+
(recommended when using for the first time), else select the `full` template.
46+
You can also provide a name for the flat file that is to be generated.
47+
Check `Create a git repository`, `Open in new session` and
48+
finally click on `Create Project` to create the initial structure.
49+
50+
## Convert a `.Rmd` file into a package
51+
52+
Following the installation and initial setup mentioned above
53+
(Select the `teaching` template and default name (`first`) for the flat filename.
54+
For the directory name, I am using `my.teaching.fusen.package`)
55+
will open a new RStudio session with an initial structure as seen in the image below:
56+
57+
![Initial structure of a {fusen} project](images/fusen/initial_structure.png){: style="display:block;margin:auto;width:69%" }
58+
59+
Since a new RStudio session is open, you will have to install {fusen} again (using `install.packages("fusen")`) in this session to be able to use its functionalities in the new session.
60+
Navigate to `dev/flat_first.Rmd` flat file and observe the different chunks present in it.
61+
The chunks in the flat file help to set up your package:
62+
63+
- `description`: In this chunk, you will add metadata about your package (for example, package author, package license, etc.).
64+
- `development`: This chunk can be used to write code for development purposes (we will not be using this for now).
65+
- `function`: In this chunk, you will write code for a function in your package.
66+
- `examples`: Here you would add examples of using the function which will become a part of the
67+
`@examples` field in the corresponding vignette.
68+
- `tests`: In this chunk, you can add unit tests for your function.
69+
70+
Add the appropriate information (title, description, author(s), email(s), license) in the `description` chunk and run it. It will generate the `DESCRIPTION` and `LICENSE` files for your package.
71+
72+
![DESCRIPTION and LICENSE files generated after the `description` chunk in the flat file is run](images/fusen/description_license.png){: style="display:block;margin:auto;width:69%" }
73+
74+
There is a default `function` chunk, named `add_one` (along with its `examples` and `tests` chunk) present in the flat file. This flat file has the minimal structure required to be transformed into a package using the function `fusen::inflate()`:
75+
76+
``` r
77+
fusen::inflate(
78+
flat_file = "dev/flat_first.Rmd",
79+
vignette_name = "Get started",
80+
check = TRUE
81+
)
82+
```
83+
84+
After running the above function, if you explore the `Files` pane on RStudio, you will notice that it looks very similar to a package structure. Notice the new directories and files that have been generated:
85+
86+
- `R` directory: It has the `add_one.R` function file, which is generated from `function-add_one` chunk of the flat file.
87+
- `man` directory: It has the `add_one.Rd` file generated from the `roxygen2` comments in the `function-add_one` chunk.
88+
- `tests` directory: It has the `testthat/test-add_one.R` generated by the `tests-add_one` chunk of the the flat file.
89+
- `vignettes` directory: It has the `get-started.Rmd` file which is generated by the `fusen::inflate()` command.
90+
- `NAMESPACE` file: It exports the `add_one` function (provided the `@export` field is mentioned in the `roxygen2` comments in the `function-add_one` chunk of the flat file).
91+
92+
![Structure after inflating the flat file](images/fusen/first_inflate.png){: style="display:block;margin:auto;width:69%" }
93+
94+
At this stage, we have a proper R package structure - if you want to you can [clean up any fusen related files and tags](#clean-fusen-related-files-and-tags) from it and can also [publish it on GitHub](#share-package-on-github)!
95+
96+
You can also add new family of functions to your package using new flat template files. I will add two more functions (`squared` and `is_even`) using:
97+
98+
``` r
99+
fusen::add_flat_template(
100+
template = "additional",
101+
dev_dir = "dev",
102+
flat_name = "squared", # and later on replace this with "is_even"
103+
)
104+
```
105+
106+
This will create a new flat file template named `dev/flat_squared.Rmd` (and `dev/flat_is_even.Rmd` when the corresponding `flat_name` is used) with the various (empty) chunks that can be populated. The chunks that I used for the respective flat files are given below:
107+
108+
<!-- markdownlint-disable-next-line MD033 -->
109+
<details>
110+
<!-- markdownlint-disable-next-line MD033 -->
111+
<summary>Square of a number</summary>
112+
113+
- `function` chunk to square a number:
114+
115+
```` markdown
116+
```{r function-squared}
117+
#' Compute squared value
118+
#'
119+
#' @param value A numeric value
120+
#'
121+
#' @return Numeric.
122+
#' @export
123+
124+
squared <- function(value) {
125+
result <- value^2
126+
return(result)
127+
}
128+
```
129+
````
130+
131+
- `examples` chunk to square a number:
132+
133+
```` markdown
134+
```{r examples-squared}
135+
squared(10)
136+
squared(73)
137+
```
138+
````
139+
140+
- `tests` chunk to test the function:
141+
142+
```` markdown
143+
```{r tests-squared}
144+
test_that("squared works", {
145+
expect_equal(squared(10), 100)
146+
expect_equal(squared(73), 5329)
147+
})
148+
```
149+
````
150+
151+
</details>
152+
153+
<!-- markdownlint-disable-next-line MD033 -->
154+
<details>
155+
<!-- markdownlint-disable-next-line MD033 -->
156+
<summary>Is a number even?</summary>
157+
158+
- `function` chunk to check if a number is even:
159+
160+
```` markdown
161+
```{r function-is_even}
162+
#' Check if a value is even
163+
#'
164+
#' @param value A numeric value
165+
#'
166+
#' @return Logical. TRUE if value is even, FALSE otherwise
167+
#' @export
168+
#'
169+
170+
is_even <- function(value) {
171+
result <- value %% 2 == 0
172+
return(result)
173+
}
174+
```
175+
````
176+
177+
- `examples` chunk to check if a number is even:
178+
179+
```` markdown
180+
```{r examples-is_even}
181+
is_even(20)
182+
is_even(47)
183+
```
184+
````
185+
186+
- `tests` chunk to test the function:
187+
188+
```` markdown
189+
```{r tests-is_even}
190+
test_that("is_even works", {
191+
expect_true(is_even(20))
192+
expect_false(is_even(47))
193+
})
194+
```
195+
````
196+
197+
</details>
198+
199+
Inflate each of the two new flat files individually using:
200+
201+
``` r
202+
fusen::inflate(
203+
flat_file = "dev/flat_squared.Rmd", # and "dev/flat_is_even.Rmd"
204+
vignette_name = "Square of a number", # and "Check if even number"
205+
check = TRUE
206+
)
207+
```
208+
209+
This will update the package to include the two new functions, their unit tests, corresponding vignettes and `.Rd` files, and the `NAMESPACE` (if the functions are exported) in the appropriate locations.
210+
211+
## Clean fusen related files and tags
212+
213+
Now that I have included all the functions that I want in this package, I will clean the package to remove any fusen related files and tags. This step is optional. It can be done using the function `fusen::sepuku()`. It will delete all files starting with `flat` in the `dev/` folder and also remove any fusen configuration file, if present.
214+
215+
## Share package on GitHub
216+
217+
Finally, I will share the package on GitHub using `fusen::init_share_on_github()`. Running this command will start the process of committing the package to GitHub. Follow along the prompts to publish the various files - it will ask you to commit the current state. Eventually, you will be redirected to GitHub where your package will appear (don't forget to return to back to RStudio as the function is still running and there are more prompts waiting for you!). Keep following the prompts and the `gh-pages` branch will be created for you on the GitHub repository. Once the `gh-pages` branch is created, you need to tell GitHub to follow it, by going to `settings > pages` and in the `Branch` drop-down menu selecting `gh-pages` instead of `None` and then clicking `Save`. Wait for a few seconds and refresh the page to see the website link deployed for your package.
218+
219+
!!! Note
220+
You will notice a `README.Rmd` (and the corresponding rendered `README.md`) on
221+
GitHub with boilerplate content. Please feel free to update the `README.Rmd` file,
222+
`knit()` it, and share the updated version on GitHub.
223+
224+
If you want to add more functionality to your package, you can continue working on the it locally, inflate any flat files that you generate, and push to GitHub.
225+
226+
[View my.fusen.teaching.package](https://github.com/SaranjeetKaur/my.teaching.fusen.package) (generated by following the above instructions and hosted on GitHub)
227+
228+
## Takeaways
229+
230+
{fusen} ensures that you are writing the documentation as well as any associated tests at the same time as writing your code (the best research software engineering practice to begin with!). It is not only useful for first time R package developers, but also for more experienced developers, in the sense that they don't have to switch between R files, tests files, and vignettes while they are prototyping their functions. Since all the related chunks at located in the same flat file, it avoids the risks of forgetting any crucial step. If you retain the flat file(s), then it is also easier to review the code, because everything related to a particular function is available in the same file.
231+
232+
## Resources
233+
234+
- [Official documentation of {fusen}](https://thinkr-open.github.io/fusen/)
235+
- [Comparison: the classical way of building packages v/s the {fusen} way](https://thinkr-open.github.io/fusen/articles/Maintain-packages-with-fusen.html?q=add_flat_template#compare-a-classical-way-of-building-packages-with-the-fusen-way)
29.6 KB
Loading
40.1 KB
Loading
20.9 KB
Loading
62.9 KB
Loading

0 commit comments

Comments
 (0)