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()andmake_clean_names(). - Dropping empty or constant columns and rows with
remove_empty()andremove_constant(). - Finding duplicate records, for example repeated participant rows, with
get_dupes(). - Producing frequency tables and crosstabs with
tabyl()and theadorn_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.
- Load the package.
library(janitor) - Standardise names.
raw %>% clean_names(). When you only need a cleaned character vector, for instance while importing, usemake_clean_names(). - Remove empty rows and columns.
raw %>% remove_empty(c("rows", "cols")) - Remove columns that never vary.
raw %>% remove_constant() - Check for duplicate records on the identifying variables.
get_dupes(raw, id_column, visit_date)(substitute your own column names). - Convert Excel serial dates.
excel_numeric_to_date(41103)returns “2012-07-13”. Decimals are ignored;include_time = TRUEreturns a POSIXlt value, and adate_systemoption accepts “mac pre-2011” for older Mac workbooks. - Tabulate.
raw %>% tabyl(var1)for one variable,tabyl(var1, var2)for two, or three variables, then addadorn_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-runnames(df)and update downstream references. - Unexpected
_2suffixes or anxcolumn. 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)







