here::here()The here package finds your project root (where your
.Rproj file lives) and builds paths from there, regardless
of where your script is located.
library(here)
# Check where here thinks your project root is
here()
# Build a path from project root
here("data", "myfile.csv") # equivalent to "project_root/data/myfile.csv"
Symptoms:
here::here()
# Error: Could not find associated project...
Diagnosis:
# Check current working directory
getwd()
# Check if .Rproj file exists in your directory tree
list.files(pattern = "\\.Rproj$", recursive = TRUE)
Solutions:
.Rproj file (not just
opening R/RStudio).Rproj file: File → New Project → Existing
Directoryset_here() in a
.here file (advanced)here()Symptoms:
read_csv(here("data", "file.csv"))
# Error: 'data/file.csv' does not exist
Diagnosis checklist:
# 1. Verify your project root
here()
# 2. Check if the file exists where you think it does
file.exists(here("data", "file.csv"))
# 3. List what's actually in that directory
list.files(here("data"))
# 4. Search for the file in your project
list.files(pattern = "file.csv", recursive = TRUE, full.names = TRUE)
# 5. Check for case sensitivity (Mac/Linux care, Windows doesn't)
# "File.csv" ≠ "file.csv" on Mac/Linux
Common fixes:
.xlsx vs
.csv)Symptoms: Your code works in the console but breaks when you knit an Rmd file.
Why this happens: When you knit, R Markdown
temporarily changes the working directory to where the .Rmd
file lives.
Solution: Always use here() for file
paths in Rmd files:
# ❌ DON'T use relative paths from Rmd location
read_csv("../../data/file.csv")
# ✅ DO use here() - works from anywhere
read_csv(here("data", "file.csv"))
For HTML dependencies in Rmd YAML:
output:
html_document:
includes:
in_header: !expr here::here("scripts", "load-feather.html")
Diagnosis:
# Check if the directory exists
dir.exists(here("output"))
# Create it if needed
dir.create(here("output"), showWarnings = FALSE, recursive = TRUE)
Best practice:
# Always create directories before writing
output_dir <- here("output", "plots")
dir.create(output_dir, showWarnings = FALSE, recursive = TRUE)
ggsave(file.path(output_dir, "myplot.png"))
# 1. Where am I?
getwd()
here()
# 2. What's my project structure?
fs::dir_tree(here()) # requires fs package
# or
list.files(recursive = TRUE)
# 3. Can R see my file?
file.exists(here("path", "to", "file.csv"))
# 4. What files ARE in that directory?
list.files(here("path", "to"))
# 5. Find the file anywhere in project
list.files(pattern = "myfile", recursive = TRUE, full.names = TRUE)
If you don’t want to use here, use
file.path() for cross-platform compatibility:
# ✅ Cross-platform safe
file.path("data", "subdir", "file.csv")
# ❌ Windows-only (breaks on Mac/Linux)
"data\\subdir\\file.csv"
# ❌ Can break on Windows
"data/subdir/file.csv" # usually works but not guaranteed
.Rproj
file)here() for file paths in scripts
and Rmd files"C:/Users/..."stopifnot(file.exists(here("data", "file.csv")))# Essential commands
here::here() # Find project root
here::here("folder", "file.csv") # Build path from root
file.exists(here("path")) # Check if file exists
dir.exists(here("folder")) # Check if directory exists
list.files(here("folder")) # List directory contents
dir.create(here("output"), recursive = TRUE) # Create directory
Try running this diagnostic code in your own project:
cat("=== Project Diagnostics ===\n")
## === Project Diagnostics ===
cat("Working directory:", getwd(), "\n")
## Working directory: C:/Users/mgopalan/Documents/c2-dataviz-2026/static/slides
cat("Project root (here):", here::here(), "\n\n")
## Project root (here): C:/Users/mgopalan/Documents/c2-dataviz-2026
cat("=== Project Structure (top level) ===\n")
## === Project Structure (top level) ===
print(list.files(here::here()))
## [1] "c2-dataviz-2022.Rproj" "config.yaml" "content"
## [4] "data" "index.Rmd" "layouts"
## [7] "netlify.toml" "nopublish" "public"
## [10] "README.md" "static" "themes"
## [13] "website-data" "wilke-purl"
cat("\n=== Looking for common data directories ===\n")
##
## === Looking for common data directories ===
common_dirs <- c("data", "Data", "input", "raw_data", "output")
for (d in common_dirs) {
if (dir.exists(here::here(d))) {
cat("✓ Found:", d, "\n")
}
}
## ✓ Found: data
## ✓ Found: Data