R PROGRAMMING • SOFTWARE CRAFT AND COMMUNICATION

Naming & Formatting — Use meaningful variable names and consistent formatting

Well-chosen names and consistent style transform opaque scripts into readable, maintainable, and collaborative R code.

Historical Context & Motivation

The question of how to name variables and structure source code is nearly as old as programming itself. In the earliest days of computing, memory constraints forced programmers to use cryptic single-character identifiers—registers were labeled A, X, or i not because those names were meaningful, but because every byte mattered. As languages evolved and teams grew, however, the cost of reading code began to exceed the cost of writing it. Research in software engineering consistently shows that developers spend roughly 70% of their time comprehending existing code, making readability a first-class engineering concern rather than an aesthetic preference.

R, originally designed by Ross Ihaka and Robert Gentleman at the University of Auckland in 1993, inherited much of its syntax from S, a language created at Bell Labs in the 1970s. Early S and R scripts were often short, exploratory, and written by a single statistician. As the R ecosystem expanded into bioinformatics, finance, machine learning, and reproducible research, the need for disciplined naming conventions and formatting standards became urgent. The timeline below traces the key milestones that shaped modern R style.

1976
S Language at Bell Labs
John Chambers creates S, establishing the dot-separated naming convention (e.g., data.frame) that persists in base R to this day.
1993
R Is Born
Ihaka and Gentleman release R, inheriting S's flexible but inconsistent naming culture—dots, underscores, and camelCase all coexist without guidance.
2005
Google's R Style Guide
Google publishes one of the first formal R style guides, recommending camelCase for variables and PascalCase for functions, sparking community debate about standardization.
2014
Tidyverse Style Guide
Hadley Wickham codifies the tidyverse style guide, advocating snake_case for all identifiers and two-space indentation, which becomes the de facto community standard.
2020
styler & lintr Maturity
Automated tools like styler and lintr reach production quality, enabling CI pipelines to enforce formatting rules automatically.

The central question this lesson addresses is deceptively simple: How should you name things in R, and how should you lay out your code on the page? The answer draws on decades of software engineering research, cognitive psychology (specifically how the brain parses symbolic text), and hard-won community consensus. Getting this right will make every project you touch—from a homework script to a production Shiny application—dramatically easier to write, debug, and extend.

Core Principles of Naming & Formatting

Good naming and formatting rest on a handful of principles that recur across every style guide and every language. These are not arbitrary rules; they derive from how human cognition processes structured text. The conceptual grid below distills the core ideas into four pillars that, taken together, form a complete framework for clean R code.

1

Intention-Revealing Names

A name should answer three questions without requiring the reader to look elsewhere: What does it hold? Why does it exist? How is it used? Replace d with elapsed_days.
2

Consistent Casing Convention

Pick one casing style—preferably snake_case—and apply it everywhere. Mixing camelCase, dot.case, and snake_case within one script forces readers to context-switch constantly.
3

Structural Whitespace

Indentation, blank lines, and spaces around operators are not decoration—they encode the logical structure of your code the way paragraphs and headings structure prose. Two-space indentation is the R community standard.
4

Scope-Proportional Length

Short-lived loop counters may use short names like i; long-lived data frames deserve longer, descriptive names like patient_demographics. The name's length should be proportional to its scope and significance.
KEY TAKEAWAY
Think of variable names as labels on filing-cabinet drawers. If every drawer is labeled "stuff," finding a specific document requires opening each one. If drawers are labeled "2024 Tax Returns" or "Health Insurance Claims," you can locate what you need in seconds. Code formatting is the equivalent of organizing those drawers into logical rows and columns instead of scattering them across a warehouse floor. Names communicate what; formatting communicates structure.

Visual Explanation — Good vs. Bad Naming

The diagram below presents two versions of the same R code snippet side by side: the left panel uses vague, inconsistently formatted identifiers, while the right panel applies the principles from Section 2. Color-coded annotations highlight exactly which rules are violated or satisfied. Study the contrast—it captures the essence of why naming and formatting matter.

The left panel demonstrates common anti-patterns: single-letter names, missing whitespace, inconsistent assignment operators, and magic numeric indices. The right panel applies snake_case naming, structural whitespace, and named indexing so the reader can understand the analytical intent without any comments.

Notice that the clean version is longer in terms of character count, yet it is faster to read. This is the central paradox of good style: investing a few extra keystrokes at write time saves orders of magnitude more time at read time. The right panel is essentially self-documenting—you can determine the analysis (a linear regression of job satisfaction on income, followed by a significance test) without a single comment.

How R Naming Conventions Work in Practice

R Identifier Rules

At the language level, R imposes minimal syntactic constraints on identifiers. A valid R name must start with a letter or a dot (if the dot is not followed by a digit), and may contain letters, digits, dots, and underscores. This permissiveness is precisely why stylistic discipline matters—the language won't save you from naming a data frame xx2. Understanding the interaction between R's syntactic rules and community conventions is essential for writing idiomatic code.

The Three Major Casing Conventions in R

The three naming conventions encountered in R and their typical usage contexts.
ConventionExampleWhere You See ItRecommendation
snake_casepatient_ageTidyverse, most modern packagesPreferred
dot.casepatient.ageBase R (legacy from S)Avoid — dots conflict with S3 method dispatch
camelCasepatientAgeBioconductor, some Shiny appsAcceptable within ecosystems that mandate it

Formatting Rules — The Tidyverse Standard

  • Indentation: Use two spaces per nesting level. Never use tabs—R's default editor uses spaces, and mixing tabs and spaces causes alignment bugs.
  • Line length: Keep lines under 80 characters. For long function calls, break after each argument and align on the opening parenthesis.
  • Spacing: Place spaces around binary operators (<-, +, ==), after commas, and before opening curly braces. No space before parentheses in function calls.
  • Assignment: Use <- for assignment, not =. Reserve = for named arguments inside function calls.
  • Curly braces: Opening brace on the same line as the control keyword; closing brace on its own line, aligned with the keyword.
⚠️ Why Dots Are Dangerous in R
In R, S3 method dispatch uses dots as separators: print.data.frame means "the print method for class data.frame." If you name a variable model.fit, R could confuse it with an S3 method called model for class fit. Using model_fit eliminates this ambiguity entirely.

Taxonomy of Names — What to Call What

Different kinds of R objects call for different naming strategies. A function should usually contain a verb because it does something; a data frame should contain a noun because it is something. The diagram below maps the major R object types to their recommended naming patterns, with concrete examples for each category.

The naming taxonomy organizes R identifiers into six categories: data objects (nouns), functions (verbs), booleans (predicates), constants (SCREAMING_SNAKE_CASE), parameters, and loop counters. The bottom banner reinforces the scope-proportional length principle.

Two patterns in this taxonomy deserve special emphasis. First, the verb_noun pattern for functions (calculate_bmi, parse_log_file) immediately tells the reader what action the function performs and what it operates on. Second, boolean prefixes like is_, has_, and should_ make conditional logic read almost like English: if (has_missing_values) { impute_data(df) } is far clearer than if (flag) { f(d) }.

Worked Example — Refactoring a Messy Script

Below, we take a realistic but poorly written R script and systematically apply naming and formatting rules. The original script loads a CSV of student grades, computes class statistics, and identifies students eligible for honors. Each refactoring step targets a specific principle.

Refactoring a Grade Analysis Script
1
Step 1 — Identify the Original CodeThe original script reads: d=read.csv("g.csv"); m=mean(d$c3); s=sd(d$c3); h=d[d$c3>90,]; cat(nrow(h)). Every identifier is a single letter, there are no spaces, the assignment uses = instead of <-, and the column c3 is meaningless without documentation.
Violations: cryptic names, no whitespace, wrong assignment operator, magic column reference.
2
Step 2 — Apply Intention-Revealing NamesReplace every single-letter identifier with a descriptive snake_case name. d becomes grade_data; m becomes mean_final_score; s becomes sd_final_score; h becomes honors_students; and the column c3 is renamed (or referenced as) final_score.
Every name now answers "what is this?" without additional context.
3
Step 3 — Fix Assignment and SpacingReplace = with <- for all variable assignments. Add spaces around every binary operator and after every comma. Separate the semicolon-chained statements onto individual lines for clarity.
Consistent <- operator; one statement per line.
4
Step 4 — Extract the Magic NumberThe threshold 90 is a magic number—its meaning is invisible. Extract it into a named constant: HONORS_THRESHOLD <- 90. Now the filtering line reads honors_students <- grade_data[grade_data$final_score > HONORS_THRESHOLD, ], which is self-explanatory.
Magic numbers replaced with a named constant in SCREAMING_SNAKE_CASE.
5
Step 5 — Compose the Final Refactored ScriptThe final script reads: HONORS_THRESHOLD <- 90 grade_data <- read.csv("grades.csv") mean_final_score <- mean(grade_data$final_score) sd_final_score <- sd(grade_data$final_score) honors_students <- grade_data[grade_data$final_score > HONORS_THRESHOLD, ] cat("Honors count:", nrow(honors_students), "\n") Every identifier is meaningful, formatting is consistent, and no external documentation is needed to understand the script's purpose.
Clean, self-documenting R script ready for collaboration and version control.

Strengths, Limitations, and Common Pitfalls

Meaningful naming and consistent formatting provide enormous benefits, but they are not without tradeoffs. Understanding these limitations prevents dogmatic over-application and helps you make pragmatic decisions in real codebases.

Strengths and limitations of disciplined naming and formatting practices.
AspectStrengthsLimitations / Pitfalls
ReadabilityDescriptive names let new team members onboard quickly; code reviews become substantive rather than deciphering exercises.Excessively long names (e.g., the_mean_of_all_final_exam_scores_for_spring_2024) hinder readability in complex expressions.
ConsistencyA uniform style reduces cognitive load, since the reader's eye learns one visual pattern and can parse structure automatically.When integrating base R (dot.case) with tidyverse (snake_case) in the same project, perfect consistency is impossible—pragmatic boundaries are needed.
ToolingTools like styler and lintr automate formatting, removing human error from whitespace and indentation.Automated formatters cannot assess the semantic quality of names—lintr will accept my_var without complaint.
Team CollaborationShared style guides minimize merge conflicts and reduce friction in pull request reviews.Enforcing style on legacy codebases can create massive diffs that obscure substantive changes; incremental adoption is safer.
PerformanceNaming and formatting have zero runtime cost—R's interpreter ignores whitespace and name length.No limitations here. This is purely a developer-time investment with no runtime penalty.
KEY TAKEAWAY
Good naming is an act of API design—even for scripts only you will read. Six months from now, you are a different programmer, and your past code is indistinguishable from a stranger's. Formatting is the visual grammar that lets both present-you and future-you parse that code's intent. Think of clean style not as overhead but as communication infrastructure that pays compound interest over the lifetime of a codebase.

Connection to Advanced Practices — Linting, CI, and Package Development

The naming and formatting principles covered in this lesson are the foundation upon which more advanced software engineering practices are built. As you progress from standalone scripts to R packages, Shiny applications, and collaborative research repositories, the stakes increase and the tooling becomes more sophisticated. The table below maps the concepts from this lesson to their advanced counterparts.

From script-level discipline to production-grade tooling.
This LessonAdvanced PracticeTool / Resource
Manual snake_case namingAutomated lint checks in CI pipelines using GitHub Actionslintr::lint_package()
Manual indentation and spacingAuto-formatting on save via IDE integration or pre-commit hooksstyler::style_pkg()
Descriptive function namesFormal API design with roxygen2 documentation and namespace exportsroxygen2, devtools
Consistent style within a scriptProject-wide style guides enforced by .lintr config files and code review policies.lintr YAML config
Named constantsConfiguration management via environment variables or config packagesconfig, dotenv

In professional R package development, CRAN's R CMD check does not enforce naming conventions, but virtually all high-quality packages on CRAN and Bioconductor follow either the tidyverse or Bioconductor style guide. Mastering the basics now will prepare you for the expectations of open-source contribution and industry R development, where code that doesn't meet style standards is routinely rejected in review regardless of its functional correctness.

Practice Problems

PROBLEM 1CONCEPTUAL
Explain why the tidyverse style guide recommends snake_case over dot.case for R identifiers, even though dot.case has a long history in the language. What specific technical issue can arise from using dots in names?
PROBLEM 2BASIC
Rewrite the following line of R code to comply with tidyverse naming and formatting conventions: avgTemp=mean(weatherData$T,na.rm=TRUE)
PROBLEM 3INTERMEDIATE
Consider this function definition. Identify all naming and formatting violations, then produce a corrected version: calcBMI <- function(w,h){ w/(h^2) }
PROBLEM 4APPLIED
You inherit a Shiny application with the following server-side code fragment. Refactor it for readability and explain your decisions: output$p1 <- renderPlot({ d <- filteredData(); plot(d$x, d$y, col=d$g, pch=16, main="") })
PROBLEM 5CRITICAL THINKING
A colleague argues that enforcing a strict style guide on an R data analysis project is unnecessary overhead, since "data science scripts are disposable—they run once, produce a figure, and never need maintenance." Construct a detailed counter-argument drawing on at least three principles from this lesson. Under what narrow circumstances, if any, might your colleague's position be defensible?

Lesson Summary

This lesson established that meaningful variable names and consistent formatting are foundational skills in R programming, not optional embellishments. We traced the evolution from S's permissive dot-case conventions through the emergence of the tidyverse style guide and modern automated tools like styler and lintr. The four core principles—intention-revealing names, consistent casing, structural whitespace, and scope-proportional length—provide a complete framework for writing clean, self-documenting R code.

We examined the naming taxonomy for R objects (nouns for data, verbs for functions, predicates for booleans, SCREAMING_SNAKE_CASE for constants), walked through a complete refactoring example, and connected these practices to advanced topics like CI-based lint enforcement and R package development. The overarching lesson is that clean code is not slower to write—it is faster to read, debug, and extend, and those activities dominate the lifecycle of every nontrivial project.

Varsity Tutors • R Programming • Naming & Formatting — Use meaningful variable names and consistent formatting