Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

janitor in R: clean_names(), get_dupes() and tabyl() for Data Cleaning

How to install janitor in R and use clean_names(), remove_empty(), get_dupes() and tabyl() in a research data-cleaning workflow, with outputs explained.

Written and maintained by CASRAI Editorial Board

Last updated

Who this is for: researchers and analysts who import spreadsheet or survey data into R and need to clean it before analysis. After reading you should be able to install the janitor package and run its core cleaning functions in a sensible order. janitor is an R package; the similarly named Python library pyjanitor is a separate project and is not covered here.

janitor is an R package whose CRAN description reads: “Simple tools for examining and cleaning dirty data. It formats column names, produces frequency tables and crosstabs, and explores duplicate records.” CRAN lists version 2.2.1, published 2024-12-22, under an MIT + file LICENSE (CRAN package page, read 2026-11-08).

What janitor is used for in research

The package vignette says its functions “expedite the initial data exploration and cleaning that comes with any new data set.” In research projects that usually means four recurring jobs:

  • Standardising column names from imported spreadsheets with clean_names() and make_clean_names().
  • Dropping empty or constant columns and rows with remove_empty() and remove_constant().
  • Finding duplicate records, for example repeated participant rows, with get_dupes().
  • Producing frequency tables and crosstabs with tabyl() and the adorn_ family, which add totals and percentages for reporting. For a full treatment of crosstabs see crosstabs in R.

The package is designed for the tidyverse and the %>% pipe, and is optimised for data imported with readr or readxl (package site, read 2026-11-08). If your source is an Excel workbook, see reading Excel files in R with readxl first.

Install or access

The package is distributed through CRAN. These are the install commands given on the package site, https://sfirke.github.io/janitor/ :

install.packages("janitor")

# development version from GitHub
remotes::install_github("sfirke/janitor")

# r-universe build
install.packages("janitor", repos = c("https://sfirke.r-universe.dev", "https://cloud.r-project.org"))

CRAN lists R (>= 3.1.2) as the minimum R version and dplyr (>= 1.0.0), lubridate, stringr and snakecase among its imports. The maintainer is Sam Firke and the source repository is github.com/sfirke/janitor.

Step-by-step: a first-pass cleaning workflow

The order below is an editorial suggestion for a typical research import; each function and argument is taken from the package documentation. Replace raw with your own data frame.

  1. Load the package. library(janitor)
  2. Standardise names. raw %>% clean_names(). When you only need a cleaned character vector, for instance while importing, use make_clean_names().
  3. Remove empty rows and columns. raw %>% remove_empty(c("rows", "cols"))
  4. Remove columns that never vary. raw %>% remove_constant()
  5. Check for duplicate records on the identifying variables. get_dupes(raw, id_column, visit_date) (substitute your own column names).
  6. Convert Excel serial dates. excel_numeric_to_date(41103) returns “2012-07-13”. Decimals are ignored; include_time = TRUE returns a POSIXlt value, and a date_system option accepts “mac pre-2011” for older Mac workbooks.
  7. Tabulate. raw %>% tabyl(var1) for one variable, tabyl(var1, var2) for two, or three variables, then add adorn_ functions for totals and percentages.

Combined in one pipeline: raw %>% clean_names() %>% remove_empty(c("rows", "cols")) %>% remove_constant().

Output and how to read it

clean_names()

The vignette example takes the names firstName, ábc@!*, % successful (2009), REPEAT VALUE, REPEAT VALUE and an empty name, and returns first_name, abc, percent_successful_2009, repeat_value, repeat_value_2 and x. Three behaviours follow from it: camelCase is split into snake_case, symbols are dropped or spelled out (“%” becomes “percent”), duplicated names get a numeric suffix (_2), and an empty name becomes x. Any code that referenced the old names must be updated.

remove_empty()

In the vignette example, a data frame with columns v1 = c(1, NA, 3), v2 = c(NA, NA, NA) and v3 = c("a", NA, "b"), piped into remove_empty(c("rows", "cols")), keeps columns v1 and v3 and rows 1 and 3. Rows and columns are dropped only when they are entirely empty.

get_dupes()

get_dupes() returns only the rows that share values on the columns you name, and adds a dupe_count column. In the vignette, get_dupes(mtcars, wt, cyl) returns four rows: two with wt 3.44 and cyl 6, and two with wt 3.57 and cyl 8. A duplicate on a few variables is not necessarily a data error; decide against your study protocol whether it is a repeat entry or a legitimate repeated measure before deleting anything.

tabyl()

The package site describes tabyl() as an improved table() that works with one, two or three variables and returns a data frame, so it can be piped into further steps.

Troubleshooting

  • Column names changed and later code fails. clean_names() renames every column; re-run names(df) and update downstream references.
  • Unexpected _2 suffixes or an x column. These come from duplicate or blank headers in the source file, as in the vignette example above. Fix the header at source if you can.
  • Name clashes with other packages. If another loaded package masks a function name, call it explicitly as janitor::get_dupes().
  • Searching for help returns Python results. pyjanitor is a separate Python library with its own documentation.

Alternatives

Each janitor task can also be done with other tools; janitor mainly shortens the code.

Task janitor function Other route
Frequency table tabyl() Base R table(), which janitor describes tabyl() as improving
Duplicate rows get_dupes() See dropping duplicates in pandas for the Python equivalent workflow
Dropping columns remove_empty(), remove_constant() See removing a column in R
Crosstabs for reporting tabyl() with adorn_ functions See crosstabs in R

janitor and the packages above are open-source and free to install from CRAN, whose package page lists janitor under an MIT + file LICENSE.

FAQ

What does the janitor package do in R?

It provides simple tools for examining and cleaning dirty data: formatting column names, producing frequency tables and crosstabs, and exploring duplicate records (CRAN description, read 2026-11-08).

How do I install janitor?

Run install.packages("janitor") for the CRAN release, or remotes::install_github("sfirke/janitor") for the development version.

Is janitor the same as pyjanitor?

No. janitor is an R package; pyjanitor is a separate Python library.

Does clean_names() change my data?

It changes only the column names, not the values.

Sources

  • CRAN, janitor package page: https://cran.r-project.org/web/packages/janitor/index.html (read 2026-11-08)
  • janitor package site: https://sfirke.github.io/janitor/ (read 2026-11-08)
  • janitor vignette: https://cran.r-project.org/web/packages/janitor/vignettes/janitor.html (read 2026-11-08)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about janitor in R: clean_names(), get_dupes() and tabyl() for Data Cleaning

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →