# Importing and Cleaning Data — R Programming

Source: https://www.geekswithgeeks.com/en/r-programming/t-import

> 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.

![Five source icons on the left with arrows converging into a single table icon on the right.](assets/figures/r-programming/section-4-map.svg) — Figure 4.1 — Importing data from many formats into tibbles.

## Importing and cleaning a messy CSV

Explicit types, missing-value markers and clean column names.

```r
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 types
```

## Check 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.

**Quiz:** Which function standardises messy column names such as "Order ID" into snake_case?

- [ ] read_csv
- [ ] glimpse
- [x] janitor::clean_names
- [ ] pivot_longer

*Answer:* janitor::clean_names. clean_names converts column names to consistent snake_case.
