Skip to main content
R, despite being a powerful language for statistical computing and data analysis, has several common anti-patterns that can lead to inefficient code, memory issues, and maintenance problems. Here are the most important anti-patterns to avoid when writing R code.
Avoid growing objects incrementally in loops. Pre-allocate memory for the final object size or use vectorized operations instead.
Avoid using apply() on data frames as it converts them to matrices, which can lead to unexpected results if columns have different types. Use lapply(), vapply(), or packages like dplyr instead.
Be consistent with subsetting operators. Use [[]] when the column name is stored in a variable or when writing functions that take column names as parameters.
Avoid using attach() as it can lead to confusing scoping issues and hard-to-find bugs. Use with(), explicit references, or pipe operators instead.
Avoid using row.names() to store actual data. Instead, include the information as a proper column in your data frame.
Avoid using for loops for operations that can be vectorized. R is optimized for vector operations, which are typically much faster.
Avoid using global variables and the <<- operator. Instead, pass values explicitly to functions and return modified values.
Use proper error handling with tryCatch() to gracefully handle errors and provide meaningful error messages.
Avoid using T and F as shortcuts for TRUE and FALSE. They are just variables that can be reassigned, potentially leading to confusing bugs.
Avoid letting R automatically convert strings to factors. Be explicit about which columns should be factors. Note that in R 4.0.0 and later, the default changed to stringsAsFactors = FALSE.
Avoid using rm(list=ls()) to clean your environment, especially in scripts or functions. It can lead to unexpected behavior and makes code less reproducible. Instead, restart R or use separate R sessions.
Use proper package management to check if packages are installed before loading them, and install them if needed.
Avoid using setwd() in scripts as it makes them less portable. Use the here package or relative paths instead.
Document your functions and scripts properly, preferably using roxygen2-style comments for functions.
Avoid using sapply() when the return type might vary. Use vapply() with an explicit return type or lapply() instead.
Choose appropriate data structures for your task. For lookups, named vectors or environments are often more efficient than data frames.
Use efficient subsetting methods, especially for large datasets. Consider using packages like data.table or dplyr for better performance.
Use consistent, descriptive naming conventions for variables and functions. The most common convention in R is snake_case (words separated by underscores).
Write tests for your functions to ensure they work correctly in different scenarios. Use packages like testthat for structured testing.
Avoid using print() statements for debugging. Use proper logging packages like logger or futile.logger instead.
Be mindful of memory usage, especially when working with large datasets. Remove large objects when they’re no longer needed and consider using packages like data.table or ff for out-of-memory processing.
Be careful with default arguments, especially when they are complex objects. Initialize them inside the function if needed.