structured revolves around the concept of structures, which is a fancy name for project templates. Well, strongly structured templates. So, it is essential to understand those structures to select the most adequate for your project.

structured defines projects by a combination of two values. The first is project level and determines the complexity of your project1. The second is project type and specifies how your project will solve your problem. The next sections give more details about each option those values can assume. Finally, at the end of this tutorial, we will also show you some ways to extend these structures to your needs.

Before we start, it is important to load some packages.

# Uncomment to install packages
## install.packages("fs")
## install.packages("remotes")
## remotes::install_github("GiuseppeTT/structured")

# Load packages
library(fs)
library(structured)

Project level

Basic

The “basic” project level is simple, minimal, but complete enough to accommodate all the project types. In other words, it is a perfect starting point for newbies and an excellent use for quick and simple projects.

The structure is composed of the following files:

structure_project(
    "basic-project",
    level = "Basic",
    type = "None"
)
dir_tree("basic-project", all = TRUE)
#> basic-project
#> ├── R
#> │   └── functions.R
#> ├── basic-project.Rproj
#> ├── data
#> ├── extra
#> └── output

The purpose of each file/folder is the following:

  • data/ Save all the pertaining data. For example, csv tabular data, the cleaned version of the csv tabular data or even a SQLite database file.

  • output/ Save anything generated that is not data. For instance, figures, tables, models, documents, etc.

  • extra/ Save any file that is not data, output or code but is related to the project. Some cases are professor instructions about a class assignment and meeting notes.

  • R/ Save auxiliary R files. That is, files that are not run directly. Some examples are ui.R and server.R, which are used by the {shiny} package.

  • R/functions.R Write your R functions used in the rest of the project. This helps keeping your code clean, similar to the effect of adding subfolder such as data/ to organize your files.

  • basic-project.Rproj (<project directory name>.Rproj) RStudio project file. The Project-oriented workflow article and the Workflow: projects chapter are great reference. In short, this little guy allows you to break free from all the evil that comes from setwd("path/that/only/works/on/my/computer") and use read_csv("data/my-data.csv") directly.

Intermediate

If the objective of the “basic” project level is getting the job done, the goal of the “intermediate” project level is getting the job done and sharable. Even if it means sharing with yourself six months in the future.

The structure is composed of the following files:

structure_project(
    "intermediate-project",
    level = "Intermediate",
    type = "None"
)
dir_tree("intermediate-project", all = TRUE)
#> intermediate-project
#> ├── .gitignore
#> ├── R
#> │   └── functions.R
#> ├── README.md
#> ├── data
#> ├── extra
#> ├── intermediate-project.Rproj
#> └── output

The purpose of the additional file/folders are the following:

  • README.md Write must read instructions about your project. Some useful topics are a quick description of what the project is about and steps on how to run it.

  • .gitignore This file represents more than its functionality. The idea here is that you use git to version control your project. This way you will never be afraid again of changing one line and breaking everything. Plus, it makes team coding much better. The Happy Git With R notes and the Git and Github chapter are great resources to learn git for R users.

Project type

Script

Examples: basic version and intermediate version

The “script” project type is the most direct approach to solving a problem. You simply code your analysis in a script, run it and its done. The product files should be available in the output/ directory.

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "script-project",
    level = "Basic",
    type = "Script"
)
dir_tree("script-project", all = TRUE)
#> script-project
#> ├── R
#> │   └── functions.R
#> ├── analysis.R
#> ├── data
#> ├── extra
#> ├── output
#> └── script-project.Rproj

The purpose of the additional file/folders are the following:

  • analysis.R Code your analysis. Some common steps are reading data, cleaning data, computing statistics and plotting.

R Markdown (Simplified)

Examples: basic version and intermediate version

The “R markdown (simplified)” project type is designed for easily creating documents from R Markdown files. Just use the knit button in your RStudio to render the Rmd file and copy the generated document to the output/ folder.

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "r-markdown-simplified-project",
    level = "Basic",
    type = "R Markdown (Simplified)"
)
dir_tree("r-markdown-simplified-project", all = TRUE)
#> r-markdown-simplified-project
#> ├── R
#> │   └── functions.R
#> ├── analysis.Rmd
#> ├── data
#> ├── extra
#> ├── output
#> └── r-markdown-simplified-project.Rproj

The purpose of the additional file/folders are the following:

  • analysis.Rmd Write and code your analysis. Some common sections are database description (read data), results (compute statistics) and conclusion. If you want to learn more about R Markdown, check its documentation.

R Markdown

Examples: basic version and intermediate version

The “R markdown” project type offers a more programmatic approach to generating documents than the “R markdown (simplified)” project type. Instead of relying on the knit button, you run a script that will automatically render all Rmd documents and move them to the output/ folder.

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "r-markdown-project",
    level = "Basic",
    type = "R Markdown"
)
dir_tree("r-markdown-project", all = TRUE)
#> r-markdown-project
#> ├── R
#> │   └── functions.R
#> ├── Rmd
#> │   └── analysis.Rmd
#> ├── data
#> ├── extra
#> ├── output
#> ├── r-markdown-project.Rproj
#> └── render.R

The purpose of the additional file/folders are the following:

  • Rmd/ Save any R Markdown file.

  • Rmd/analysis.Rmd Write and code your analysis. Some common sections are database description (read data), results (compute statistics) and conclusion. If you want to learn more about R Markdown, check its documentation.

  • render.R You do not have to do anything as this script is automatically configured. Just run it to render the R Markdown files.

Observation: If you want to use the knit button in this structure, you need to configure the knit directory to the project directory. You can do that by clicking “Knit” -> “Knit Directory” -> “Project Directory”. For more information, check the The working directory for R code chunks subchapter.

Targets

Examples: basic version and intermediate version

The “targets” project type is specially useful for big and slow to run analysis. The idea here is to leverage the {targets} package to organize your analysis code even more and run only the necessary parts when changing something.

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "targets-project",
    level = "Basic",
    type = "Targets"
)
dir_tree("targets-project", all = TRUE)
#> targets-project
#> ├── R
#> │   └── functions.R
#> ├── _targets.R
#> ├── data
#> ├── extra
#> ├── output
#> └── targets-project.Rproj

The purpose of the additional file/folders are the following:

  • _targets.R Code your analysis workflow. I recommend reading the {targets} documentation

Shiny

Examples: basic version and intermediate version

The “shiny” project type offers a different approach to projects. Instead of producing some static files (e.g., images and pdfs), it uses the {shiny} package to build a web application. One big use case are interactive dashboards (check the {shinydashboard} package).

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "shiny-project",
    level = "Basic",
    type = "Shiny"
)
dir_tree("shiny-project", all = TRUE)
#> shiny-project
#> ├── R
#> │   ├── functions.R
#> │   ├── global.R
#> │   ├── server.R
#> │   └── ui.R
#> ├── app.R
#> ├── data
#> ├── extra
#> ├── output
#> └── shiny-project.Rproj

The purpose of the additional file/folders are the following:

  • R/global.R Define global variables. For instance, a data frame containing the data to be presented in the dashboard.

  • R/ui.R Define the app UI (user interface). In plain English, what the user sees and interact in their browser.

  • R/server.R Define the app server. In other words, the code responsible for doing calculations, generating plots, etc.

  • app.R You do not have to do anything as this script is automatically configured. Just run it to host the shiny application. For more information, check the {shiny} documentation.

None

The “none” project type is, well…, nothing. It adds no file nor folder to the project, except for the files already included by the chosen project level. In summary, it is good option if you just want the raw template without an optioned approach to solve your problem.

Using the “basic” project level, the structure is composed of the following files:

structure_project(
    "none-project",
    level = "Basic",
    type = "None"
)
dir_tree("none-project", all = TRUE)
#> none-project
#> ├── R
#> │   └── functions.R
#> ├── data
#> ├── extra
#> ├── none-project.Rproj
#> └── output

Extensions

All the presented structures were designed with the special consideration to be flexible. Therefore, if you feel you need to add a file, folder or even delete some, please do so!

The “subfolder script extension” example (basic version and intermediate version) illustrates this process. It adds subfolders such as data/clean/ and output/figure/ to further divide the data and output files. Moreover, the analysis.R script was moved to the script/ folder along with a new clean.R file responsible for cleaning the data before the analysis.


  1. We should always aim for the simplest solution, but sometimes complexity is unavoidable.↩︎