Written and maintained by CASRAI Editorial Board
Last updated
To read a CSV file into R, call read.csv("data.csv") from base R, or read_csv("data.csv") from the readr package. Both return a table of rows and columns; they differ in their defaults for missing values, type detection and the object they return. Choosing the arguments explicitly, rather than trusting the defaults, is what makes a reload of the same file give the same column types every time.
What it is used for in research
Most statistical work in R starts with a delimited text file exported from a spreadsheet, a survey platform or an instrument. Reading that file correctly is the first analysis step: a column that arrives as text instead of numbers, or a misread missing-value code, changes every result that follows. A stray unit or comma in one cell is enough to turn a numeric column into text, which is one of the causes of a failed normality check described in Shapiro-Wilk test in R. If your file is tab-separated rather than comma-separated, see what a TSV file is.
Install or access
read.csv() belongs to the utils package that ships with R, so nothing needs installing. read_csv() comes from the readr package, installed once from CRAN and loaded in each session:
install.packages("readr")
library(readr)
Step-by-step: read a CSV file in R
Option 1: base R with read.csv
- Put the file in your working directory or note its full path. Use forward slashes in paths, also on Windows.
- Read it, stating the header choice explicitly. The R Data Import/Export manual recommends specifying the
headerargument explicitly:df <- read.csv("data.csv", header = TRUE) - Inspect the result with
str(df)andhead(df)before doing anything else.
According to the R manual, read.csv is identical to read.table except for its defaults: sep = ",", header = TRUE, fill = TRUE and the comment character disabled.
Option 2: readr with read_csv
- Load the package with
library(readr). - Read the file:
df <- read_csv("data.csv") - Read the message readr prints about the column types it guessed, then confirm them with
spec(df)or by printing the result.
The readr reference describes read_csv() as convenient and fast but not robust: types are guessed from a limited number of rows, so give col_types when the file matters.
Output and how to read it
read.csv() returns a data frame. read_csv() returns a tibble, which prints only the first rows with each column’s type under its name. In either case check three things: the number of rows and columns matches the file, each column has the type you expect (numeric, character, date), and missing values appear as NA. For base R use str(df). For readr, if parsing went wrong, readr issues a warning, and problems(df) lists the rows and columns it could not parse.
Reading a CSV file in R: encoding, delimiters and column types
Choose the delimiter and decimal mark
Spreadsheets in many locales export semicolon-separated files with a decimal comma. Use read.csv2() (sep = ";", dec = ",") or readr’s read_csv2() for those. For tab-separated files base R offers read.delim().
Set the encoding
For non-ASCII text, the R manual advises making sure the file is read in the correct encoding. In base R pass fileEncoding; the manual notes that a UTF-8 file with a byte order mark may need fileEncoding = "UTF-8-BOM" on Unix-alikes. In readr, the encoding is part of locale(), which also holds the time zone and decimal mark; the default locale is US-centric.
Fix the column types and the missing-value codes
Base R decides column types with type.convert unless you pass colClasses. readr guesses from up to 1000 rows by default (guess_max); raise it or supply col_types, either as a cols() specification or a compact string. If your file uses a code such as -99 or "." for missing, say so with na.strings (base) or na (readr) instead of recoding afterwards.
Defaults compared
| Behaviour | read.csv (base R) | read_csv (readr) |
|---|---|---|
| Returns | Data frame | Tibble |
| Header row | header = TRUE |
col_names = TRUE |
| Missing-value strings | na.strings = "NA"; blank fields are also missing in logical, integer, numeric and complex columns |
na = c("", "NA") |
| Type detection | type.convert, or colClasses if given |
Guessed from up to guess_max rows (1000 by default); override with col_types |
| Comment lines | Disabled (comment.char = "") |
Disabled (comment = "") |
| Rows to skip / limit | skip = 0, nrows = -1 |
skip = 0, n_max = Inf |
Troubleshooting
- Everything lands in one column. The file probably uses semicolons or tabs. Try
read.csv2(),read.delim()orread_csv2(). - Accented characters look garbled, or the first column name starts with strange characters. Set
fileEncoding(including"UTF-8-BOM"for a byte order mark) or, in readr, alocale()with the right encoding. - A numeric column is read as text. A non-numeric entry in the column forces text. Find the offending cell, correct the source file, or set the column type explicitly. In readr, raise
guess_maxor usecol_types, then checkproblems(). - An error about the number of elements on a line. Rows have different lengths. Base R’s
fill = TRUEpads short rows (the default inread.csv), andcount.fields()shows how many fields each line has so you can find the bad line. - An extra first column of row numbers. The R manual gives
read.csv(..., row.names = 1)as the way to read a CSV file that includes row names. - A very large file is slow or uses too much memory in base R. The R Data Import/Export manual suggests setting
comment.char = "", givingcolClassesas atomic types, and settingnrowsto a mild over-estimate of the row count. - Console noise about column specifications. Set
show_col_types = FALSEinread_csv()once you have recorded the types you want.
Keep the read reproducible
Write the arguments that matter into the script: header, the missing-value codes, the encoding and the column types. Defaults can differ between functions and between locales, so a script that states them reads the same file the same way on a colleague’s machine. Keep the original CSV unchanged and do all cleaning in code.
Free alternatives
| Option | Where it comes from | Notes |
|---|---|---|
read.csv() |
utils package, included with R | No extra install; returns a data frame |
read_csv() |
readr package, from CRAN | Returns a tibble; column types set with col_types |
Other languages read CSV files too; see data analysis tools in Python for the Python route, or JASP for a point-and-click option that opens CSV files without code.
FAQ
How do I read a CSV file in R?
Use read.csv("file.csv") in base R or readr::read_csv("file.csv"). Both assume a header row and comma separators. Check the result with str() or by printing the tibble.
What is the difference between read.csv and read_csv?
read.csv is a base R function that returns a data frame; read_csv is from readr and returns a tibble. They differ in how they treat missing values, whitespace and type guessing, as the table above shows.
How do I read a CSV file with a semicolon separator?
Use read.csv2() or read_csv2(). Both expect ; between fields and , as the decimal mark.
Why does read.csv turn my numbers into text?
One non-numeric value in a column is enough. Locate it, fix the file or set colClasses (base) or col_types (readr), and check for unusual missing-value codes with na.strings or na.
Sources
- R Core Team, read.table / read.csv reference (utils package), checked 2026-10-29.
- R Core Team, R Data Import/Export, section 2.1 Variations on read.table, checked 2026-10-29.
- Tidyverse, readr: read_delim and read_csv reference, checked 2026-10-29.








