Skip to main content
v2026.11,858 entries · CC-BY 4.0

Reading CSV Into R: read.csv vs read_csv

How to read a CSV file in R with base read.csv or readr read_csv, how their defaults differ, and how to fix encoding, delimiter and type problems.

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

  1. Put the file in your working directory or note its full path. Use forward slashes in paths, also on Windows.
  2. Read it, stating the header choice explicitly. The R Data Import/Export manual recommends specifying the header argument explicitly:
    df <- read.csv("data.csv", header = TRUE)
  3. Inspect the result with str(df) and head(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

  1. Load the package with library(readr).
  2. Read the file:
    df <- read_csv("data.csv")
  3. 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() or read_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, a locale() 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_max or use col_types, then check problems().
  • An error about the number of elements on a line. Rows have different lengths. Base R’s fill = TRUE pads short rows (the default in read.csv), and count.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 = "", giving colClasses as atomic types, and setting nrows to a mild over-estimate of the row count.
  • Console noise about column specifications. Set show_col_types = FALSE in read_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

Follow CASRAI

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

Ask CASRAI · free to try

Ask about Reading CSV Into R: read.csv vs read_csv

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 →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.