Skip to course content
Free R data course

R Foundations for Data Analysis

Unit 02.02: Names are the cheapest documentation

You will read your own code far more often than you write it. Names are where that time is won or lost.

A good name says what the rows are

df, data, x, temp and df2 tell a reader nothing and force them to scroll back to the creating line. ward_visits says what one row is. Column names have the same job: visits and ward survive being read out of context, a and b do not.

R will let you name an object after a function โ€” including mean, data, sum or c โ€” without complaint. The function still works, because R looks in a different place for something being *called*. But every reader now has to work out which one you meant, and eventually somebody writes code that genuinely breaks.

Names also have syntax rules. Spaces, leading digits and punctuation are not allowed, and functions that import data will repair offending names rather than refuse them.

This block contrasts two versions of the same table and then abuses a name on purpose.


# Names are the cheapest documentation you will ever write.

# Vague, and one of these shadows a base R function.
df <- data.frame(a = c(412, 388), b = c("North", "South"))

# Clear: the name says what the rows are and what the columns hold.
ward_visits <- data.frame(visits = c(412, 388), ward = c("North", "South"))

cat("Column names carrying meaning:", paste(names(ward_visits), collapse = ", "), "\n\n")

# R lets you name an object after a function. The function still works,
# but every reader now has to check which one you meant.
mean <- 99
cat("mean is now the number:", mean, "\n")
cat("but mean() still calls the function:", base::mean(c(412, 388)), "\n")
rm(mean)

# Names that are not syntactically valid get repaired -- rarely how you hoped.
awkward <- c("Ward Name", "2024 visits", "rate %")
cat("\nRepaired:", paste(make.names(awkward), collapse = " | "), "\n")

The clear version's columns read as visits, ward. After mean <- 99, mean is the number 99 while base::mean() still returns 400 for the two wards โ€” both are true at once, which is precisely the confusion to avoid. The repair at the end turns Ward Name, 2024 visits and rate % into Ward.Name, X2024.visits and rate.., so the imported names are legal and nobody would have chosen them.

The mistake this prevents

The mistake is naming a variable data because the table holds data. It shadows a base function, and it tells the reader nothing that the file extension did not already say.

Takeaway

Name objects after what a row represents and columns after what they hold. Use lower case with underscores, avoid the names of common functions, and fix imported column names deliberately rather than living with the repair.