Skip to content

Commit c4e09e5

Browse files
authored
Merge pull request #10 from NCEAS/coding-tips-dev
Coding tips dev
2 parents 9783183 + eb000f2 commit c4e09e5

File tree

10 files changed

+127
-6
lines changed

10 files changed

+127
-6
lines changed

_freeze/best_practices/execute-results/html.json

+2-2
Large diffs are not rendered by default.

_freeze/modules_best-practices/file-paths/execute-results/html.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"hash": "6c3f32b1566130c17d7b77285dc44aae",
2+
"hash": "0b74bcb0ee0f9019d9c30ea7a67b3169",
33
"result": {
4-
"markdown": "\nThis section contains our recommendations for handling **file paths**. When you code collaboratively (e.g., with GitHub), accounting for the difference between your folder structure and those of your colleagues becomes critical. Ideally your code should be completely agnostic about (1) the operating system of the computer it is running on (i.e., Windows vs. Mac) and (2) the folder structure of the computer. We can--fortunately--handle these two considerations relatively simply.\n\nThis may seem somewhat dry but it is worth mentioning that failing to use relative file paths is a significant hindrance to reproducibility (see [Trisovic et al. 2022](https://www.nature.com/articles/s41597-022-01143-6)).\n\n### 1. Preserve File Paths as Objects Using `file.path`\n\nDepending on the operating system of the computer, the slashes between folder names are different (`\\` versus `/`). The `file.path` function automatically detects the computer operating system and inserts the correct slash. We recommend using this function and assigning your file path to an object.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmy_path <- file.path(\"path\", \"to\", \"my\", \"file\")\nmy_path\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"path/to/my/file\"\n```\n:::\n:::\n\n\nOnce you have that path object, you can use it everywhere you import or export information to/from the code (with another use of `file.path` to get the right type of slash!).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Import\nmy_raw_data <- read.csv(file = file.path(my_path, \"raw_data.csv\"))\n\n# Export\nwrite.csv(x = data_object, file = file.path(my_path, \"tidy_data.csv\"))\n```\n:::\n\n\n### 2. Create Necessary Sub-Folders in the Code with `dir.create`\n\nUsing `file.path` guarantees that your code will work regardless of the upstream folder structure but what about the folders that you need to export or import things to/from? For example, say your `graphs.R` script saves a couple of useful exploratory graphs to the \"Plots\" folder, how would you guarantee that everyone running `graphs.R` *has* a \"Plots folder\"? You can use the `dir.create` function to create the folder in the code (and include your path object from step 1!).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Create needed folder\ndir.create(path = file.path(my_path, \"Plots\"), showWarnings = FALSE)\n\n# Then export to that folder\nggplot2::ggsave(filename = file.path(my_path, \"Plots\", \"my_plot.png\"))\n```\n:::\n\n\nThe `showWarnings` argument of `dir.create` simply warns you if the folder you're creating already exists or not. There is no negative to \"creating\" a folder that already exists (nothing is overwritten!!) but the warning can be confusing so we can silence it ahead of time.\n\n### File Paths Summary\n\nWe strongly recommend following these guidelines so that your scripts work regardless of (1) the operating system, (2) folders \"upstream\" of the working directory, and (3) folders within the project. This will help your code by flexible and reproducible when others are attempting to re-run your scripts!\n",
4+
"markdown": "\nThis section contains our recommendations for handling **file paths**. When you code collaboratively (e.g., with GitHub), accounting for the difference between your folder structure and those of your colleagues becomes critical. Ideally your code should be completely agnostic about (1) the operating system of the computer it is running on (i.e., Windows vs. Mac) and (2) the folder structure of the computer. We can--fortunately--handle these two considerations relatively simply.\n\nThis may seem somewhat dry but it is worth mentioning that failing to use relative file paths is a significant hindrance to reproducibility (see [Trisovic et al. 2022](https://www.nature.com/articles/s41597-022-01143-6)).\n\n### 1. Preserve File Paths as Objects Using `file.path`\n\nDepending on the operating system of the computer, the slashes between folder names are different (`\\` versus `/`). The `file.path` function automatically detects the computer operating system and inserts the correct slash. We recommend using this function and assigning your file path to an object.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmy_path <- file.path(\"path\", \"to\", \"my\", \"file\")\nmy_path\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"path/to/my/file\"\n```\n:::\n:::\n\n\nOnce you have that path object, you can use it everywhere you import or export information to/from the code (with another use of `file.path` to get the right type of slash!).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Import\nmy_raw_data <- read.csv(file = file.path(my_path, \"raw_data.csv\"))\n\n# Export\nwrite.csv(x = data_object, file = file.path(my_path, \"tidy_data.csv\"))\n```\n:::\n\n\n### 2. Create Necessary Sub-Folders in the Code with `dir.create`\n\nUsing `file.path` guarantees that your code will work regardless of the upstream folder structure but what about the folders that you need to export or import things to/from? For example, say your `graphs.R` script saves a couple of useful exploratory graphs to the \"Plots\" folder, how would you guarantee that everyone running `graphs.R` *has* a \"Plots folder\"? You can use the `dir.create` function to create the folder in the code (and include your path object from step 1!).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Create needed folder\ndir.create(path = file.path(my_path, \"Plots\"), showWarnings = FALSE)\n\n# Then export to that folder\nggplot2::ggsave(filename = file.path(my_path, \"Plots\", \"my_plot.png\"))\n```\n:::\n\n\nThe `showWarnings` argument of `dir.create` simply warns you if the folder you're creating already exists or not. There is no negative to \"creating\" a folder that already exists (nothing is overwritten!!) but the warning can be confusing so we can silence it ahead of time.\n\n### File Paths Summary\n\nWe strongly recommend following these guidelines so that your scripts work regardless of (1) the operating system, (2) folders \"upstream\" of the working directory, and (3) folders within the project. This will help your code by flexible and reproducible when others are attempting to re-run your scripts!\n\nAlso, for more information on how to read files in cloud storage locations such as Google Drive, Box, Dropbox, etc., please refer to our [Other Tutorials](https://nceas.github.io/scicomp.github.io/tutorials.html).",
55
"supporting": [],
66
"filters": [
77
"rmarkdown/pagebreak.lua"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"hash": "c0f63e8f7edc4c7bbdaeaab27ed88ab8",
3+
"result": {
4+
"markdown": "The above section shows how R users can access their data stored on Google Drive, but how about other types of cloud storage like Box or Dropbox? If your data or your team's data is synced to the cloud through those tools, we recommend that all group members store relevant file paths in their own respective JSON file. Then everyone can read those file paths using the [`jsonlite` R package](https://cran.r-project.org/web/packages/jsonlite/index.html)! \n\nThe main advantage of this method is that you and your group members do not have to manually change the file paths in each script whenever a different person runs it!\n\n### Prerequisites\n\nTo follow along with this tutorial you will need to take the following steps:\n\n- [Download R](https://cran.r-project.org/)\n\n- [Download RStudio](https://www.rstudio.com/products/rstudio/download/)\n\n- Make sure you have access to your cloud storage files on your local machine\n\nFeel free to skip any steps that you have already completed!\n\n### Copy the desired file paths\n\nFirst, navigate to the folder(s) that contain the files that you and your team most frequently need to access. Copy the absolute path to each needed folder. On Mac, you can right-click and then \"Copy ... as Pathname\" (see below).\n\n<p align=\"center\">\n<img src=\"images/tutorial_jsonlite/jsonlite-1.png\" width = \"90%\" />\n</p>\n\nIf you have multiple paths, feel free to paste them into an empty text file for now.\n\n### Create the JSON file\n\nOnce you have the absolute file paths, open RStudio to the main working directory for your project. At the top left corner, click on File -> New File -> Text File. \n\nType the following lines into the file, except replace `YOUR_ABSOLUTE_PATH` with your path. Keep the quotation marks around the path. \n\n\n::: {.cell}\n\n```{.r .cell-code}\n{\n\"data_path\":\"YOUR_ABSOLUTE_PATH\"\n}\n```\n:::\n\n\nYou can customize the name of this path but make sure everyone in your team have the same name(s)! For example, if `data_path` refers to the folder containing all of the data for the group, then everyone should have a `data_path` in their own respective JSON file pointing to the same data folder. The absolute file path will be unique for each person, though. \n\nIf you have multiple paths, you can save them like so:\n\n\n::: {.cell}\n\n```{.r .cell-code}\n{\n\"raw_data_path\":\"YOUR_ABSOLUTE_PATH\",\n\"tidy_data_path\":\"YOUR_ABSOLUTE_PATH\"\n}\n```\n:::\n\n\nSave this file as `paths.json` in your main working directory. \n\n### Put the JSON file in `gitignore`\n\nNavigate to the `gitignore` file of your project and list `paths.json` as one of the files to ignore. We don't want to push this file to GitHub since everyone's own `paths.json` will look different and you wouldn't want to accidentally overwrite your teammate's custom absolute path!\n\n### Install `jsonlite`\n\nIf you don't have `jsonlite` already, install it with:\n\n\n::: {.cell}\n\n```{.r .cell-code}\ninstall.packages(\"jsonlite\")\n```\n:::\n\n\n### Access your files in cloud storage\n\nNow whenever you want to access the files for your group, you can load `jsonlite` and run its `read_json()` function. If your path was not saved as `data_path` then in the code below, make sure to replace `data_path` with the actual name.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Load jsonlite\nlibrary(\"jsonlite\")\n\n# Get the path to your files\npath_to_data <- jsonlite::read_json(\"paths.json\")$data_path\n```\n:::\n\n\nAnd `path_to_data` will contain the path to the folder where all your relevant files live! \n\nIf you combine this path with the [`file.path()` function](https://nceas.github.io/scicomp.github.io/best_practices.html#preserve-file-paths-as-objects-using-file.path) then you'll have a powerful, flexible tool for managing file paths!\n\nFor example, if `example.csv` lives in the folder that `path_to_data` points to, then you **and your team members** can read `example.csv` like so:\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Read the csv reproducibly\nexample <- read.csv(file = file.path(path_to_data, \"example.csv\"))\n```\n:::",
5+
"supporting": [],
6+
"filters": [
7+
"rmarkdown/pagebreak.lua"
8+
],
9+
"includes": {},
10+
"engineDependencies": {},
11+
"preserve": {},
12+
"postProcess": true
13+
}
14+
}

_freeze/tutorials/execute-results/html.json

+2-2
Large diffs are not rendered by default.

best_practices.qmd

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Check the headings below or in the table of contents on the right of this page t
3030
<img src="images/lter-photos/penguins.jpg" width="100%"/>
3131
</p>
3232

33+
## Good Naming Conventions
34+
35+
{{< include /modules_best-practices/naming-conventions.qmd >}}
36+
3337
## Package Loading
3438

3539
{{< include /modules_best-practices/pkg-loading.qmd >}}
714 KB
Loading

modules_best-practices/file-paths.qmd

+2
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,5 @@ The `showWarnings` argument of `dir.create` simply warns you if the folder you'r
3939
### File Paths Summary
4040

4141
We strongly recommend following these guidelines so that your scripts work regardless of (1) the operating system, (2) folders "upstream" of the working directory, and (3) folders within the project. This will help your code by flexible and reproducible when others are attempting to re-run your scripts!
42+
43+
Also, for more information on how to read files in cloud storage locations such as Google Drive, Box, Dropbox, etc., please refer to our [Other Tutorials](https://nceas.github.io/scicomp.github.io/tutorials.html).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
When you first start working on a project with your group members, figuring out what to name your folders/files may not be at the top of your priority list. However, following a good naming convention will allow team members to quickly locate files and figure out what they contain. The organized naming structure will also allow new members of the group to be onboarded more easily!
2+
3+
Here is a summary of some naming tips that we recommend. These were taken from the [Reproducibility Best Practices module](https://lter.github.io/ssecr/mod_reproducibility.html#naming-tips) in the LTER's SSECR course. Please feel free to refer to the aforementioned link for more information.
4+
5+
- Names should be informative
6+
- An ideal file name should give some information about the file’s contents, purpose, and relation to other project files.
7+
- For example, if you have a bunch of scripts that need to be run in order, consider adding step numbers to the start of each file name (e.g., "01_harmonize_data.R" or "step01_harmonize_data.R").
8+
- Names should avoid spaces and special characters
9+
- Spaces and special characters (e.g., é, ü, etc.) in folder/file names may cause errors when someone with a Windows computer tries to read those file paths. You can replace spaces with delimiters like underscores or hyphens to increase machine readability.
10+
- Follow a consistent naming convention throughout!
11+
- If you and your group members find a naming convention that works, stick with it! Having a consistent naming convention is key to getting new collaborators to follow it.
12+

tutorial-scaffold_jsonlite.qmd

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
The above section shows how R users can access their data stored on Google Drive, but how about other types of cloud storage like Box or Dropbox? If your data or your team's data is synced to the cloud through those tools, we recommend that all group members store relevant file paths in their own respective JSON file. Then everyone can read those file paths using the [`jsonlite` R package](https://cran.r-project.org/web/packages/jsonlite/index.html)!
2+
3+
The main advantage of this method is that you and your group members do not have to manually change the file paths in each script whenever a different person runs it!
4+
5+
### Prerequisites
6+
7+
To follow along with this tutorial you will need to take the following steps:
8+
9+
- [Download R](https://cran.r-project.org/)
10+
11+
- [Download RStudio](https://www.rstudio.com/products/rstudio/download/)
12+
13+
- Make sure you have access to your cloud storage files on your local machine
14+
15+
Feel free to skip any steps that you have already completed!
16+
17+
### Copy the desired file paths
18+
19+
First, navigate to the folder(s) that contain the files that you and your team most frequently need to access. Copy the absolute path to each needed folder. On Mac, you can right-click and then "Copy ... as Pathname" (see below).
20+
21+
<p align="center">
22+
<img src="images/tutorial_jsonlite/jsonlite-1.png" width = "90%" />
23+
</p>
24+
25+
If you have multiple paths, feel free to paste them into an empty text file for now.
26+
27+
### Create the JSON file
28+
29+
Once you have the absolute file paths, open RStudio to the main working directory for your project. At the top left corner, click on File -> New File -> Text File.
30+
31+
Type the following lines into the file, except replace `YOUR_ABSOLUTE_PATH` with your path. Keep the quotation marks around the path.
32+
33+
```{r create-json-1, eval = F}
34+
{
35+
"data_path":"YOUR_ABSOLUTE_PATH"
36+
}
37+
```
38+
39+
You can customize the name of this path but make sure everyone in your team have the same name(s)! For example, if `data_path` refers to the folder containing all of the data for the group, then everyone should have a `data_path` in their own respective JSON file pointing to the same data folder. The absolute file path will be unique for each person, though.
40+
41+
If you have multiple paths, you can save them like so:
42+
43+
```{r create-json-2, eval = F}
44+
{
45+
"raw_data_path":"YOUR_ABSOLUTE_PATH",
46+
"tidy_data_path":"YOUR_ABSOLUTE_PATH"
47+
}
48+
```
49+
50+
Save this file as `paths.json` in your main working directory.
51+
52+
### Put the JSON file in `gitignore`
53+
54+
Navigate to the `gitignore` file of your project and list `paths.json` as one of the files to ignore. We don't want to push this file to GitHub since everyone's own `paths.json` will look different and you wouldn't want to accidentally overwrite your teammate's custom absolute path!
55+
56+
### Install `jsonlite`
57+
58+
If you don't have `jsonlite` already, install it with:
59+
60+
```{r install-json, eval = F}
61+
install.packages("jsonlite")
62+
```
63+
64+
### Access your files in cloud storage
65+
66+
Now whenever you want to access the files for your group, you can load `jsonlite` and run its `read_json()` function. If your path was not saved as `data_path` then in the code below, make sure to replace `data_path` with the actual name.
67+
68+
```{r read-json-1, eval = F}
69+
# Load jsonlite
70+
library("jsonlite")
71+
72+
# Get the path to your files
73+
path_to_data <- jsonlite::read_json("paths.json")$data_path
74+
```
75+
76+
And `path_to_data` will contain the path to the folder where all your relevant files live!
77+
78+
If you combine this path with the [`file.path()` function](https://nceas.github.io/scicomp.github.io/best_practices.html#preserve-file-paths-as-objects-using-file.path) then you'll have a powerful, flexible tool for managing file paths!
79+
80+
For example, if `example.csv` lives in the folder that `path_to_data` points to, then you **and your team members** can read `example.csv` like so:
81+
82+
```{r read-json-2, eval = F}
83+
# Read the csv reproducibly
84+
example <- read.csv(file = file.path(path_to_data, "example.csv"))
85+
```

tutorials.qmd

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Some of the content that we produce is not as detailed as our full workshops but
88

99
{{< include /tutorial-scaffold_googledrive-auth.qmd >}}
1010

11+
## Using the `jsonlite` R Package
12+
13+
{{< include /tutorial-scaffold_jsonlite.qmd >}}
14+
1115
## Building a Website with Quarto
1216

1317
{{< include /tutorial-scaffold_quarto-website.qmd >}}

0 commit comments

Comments
 (0)