Lesson 10 / 25
Importing and Cleaning Data
Read CSV, Excel and other files and clean column names and types.
Getting data in
Real analysis starts with importing data. readr's read_csv() reads CSV files quickly into tibbles, guessing column types and reporting them so you can check; specify types explicitly with col_types for reliable pipelines, and handle Indian number formats or other locales with locale(). readxl's read_excel() reads .xlsx and .xls sheets (with sheet and range arguments), haven reads SPSS, Stata and SAS files, jsonlite reads JSON, and DBI with a driver (such as RPostgres or RSQLite) queries databases, with dbplyr translating dplyr code to SQL. arrow reads Parquet files and datasets larger than memory. After importing, clean the data: standardise column names with janitor::clean_names() (snake_case), fix types (parse_number() strips currency symbols and commas), trim whitespace, handle missing values consistently (na = c("", "NA", "-")), and check for duplicates. Save cleaned data in a typed format such as Parquet or .rds rather than CSV to preserve types.
Many sources, one tibble
Different importers bring CSV, Excel, JSON, databases and Parquet into the same tidy table format.
Importing and cleaning a messy CSV
Explicit types, missing-value markers and clean column names.
library(readr)
library(dplyr)
library(janitor)
sales_raw <- read_csv(
"data/sales_2026.csv",
na = c("", "NA", "-"),
col_types = cols(
`Order ID` = col_character(),
`Order Date` = col_date(format = "%d/%m/%Y"),
`Amount (INR)` = col_character(),
City = col_character()
)
)
sales <- sales_raw |>
clean_names() |> # order_id, order_date, amount_inr, city
mutate(
amount_inr = parse_number(amount_inr), # "Rs 1,200" -> 1200
city = stringr::str_to_title(stringr::str_trim(city))
) |>
distinct(order_id, .keep_all = TRUE) # drop duplicate orders
problems(sales_raw) # rows readr could not parse
write_rds(sales, "data/sales_clean.rds") # keeps column typesCheck readr's column report
When read_csv() guesses types, it prints them. A column you expected to be numeric showing as character usually means stray text such as "N/A" or currency symbols that need cleaning.
Quick check: Which function standardises messy column names such as "Order ID" into snake_case?
- read_csv
- glimpse
- janitor::clean_names
- pivot_longer
Answer
janitor::clean_names — clean_names converts column names to consistent snake_case.