๐ Tutorial ยท 6 min read
How to Open a CSV File in R
To open a CSV in R, call read.csv("data.csv") for a comma-separated file with headers, read_csv("data.csv") from readr for a tibble, or fread("data.csv") from data.table for the fastest read of a large file. Base R covers the common case; the two other packages exist because they are faster and quieter about types. What goes wrong is rarely the function โ it is the separator, the encoding, or a column that R silently converts to a number. This guide is the three functions, the arguments worth setting, and how to fix an import that comes back wrong.
The quick answer
# Base R โ ships with R, no package to install
df <- read.csv("data.csv", stringsAsFactors = FALSE)
# readr โ faster, returns a tibble, fewer surprises
library(readr)
df <- read_csv("data.csv")
# data.table โ fastest for large files, returns a data.table
library(data.table)
df <- fread("data.csv")
# Semicolon-separated file (common in European exports)
df <- read.csv2("data.csv") # or read.csv("data.csv", sep = ";")
If you only need the file in memory once, read.csv is enough. Reach for readr or data.table when the file is big or the types matter.
read.csv: the base-R path
read.csv is a wrapper around read.table with three defaults already set: header = TRUE (the first row is column names), sep = ",", and fill = TRUE. That covers a clean export. The arguments that matter on real files:
stringsAsFactors = FALSEโ since R 4.0.0 this is already the default, so text stays text instead of becoming a factor.colClasses = "character"โ force every column to text, the fix for leading zeros, long IDs and scientific notation.na.strings = c("", "NA", "N/A")โ decide explicitly what counts as a missing value; by default a blank field becomesNAbut the string "N/A" may not.check.names = TRUEโ makes R turn a header such as2024 totalintoX2024.total. Set it toFALSEif you need the original names.
# Keep every column as text so IDs survive intact
df <- read.csv("accounts.csv", colClasses = "character")
read_csv and fread: faster, and stricter about types
For files larger than a few hundred thousand rows, the parsing speed of base R becomes visible. readr::read_csv and data.table::fread both parse multi-threaded and are markedly quicker on the same file.
read_csv returns a tibble and prints a column-spec line ("colnames and types") so you can see how it guessed each column. That message is useful, not noise: it is where you catch a zip code read as double before it bites you.
library(readr)
df <- read_csv("data.csv",
col_types = cols(zip = "c", id = "c")) # c = character
fread is usually the fastest option of the three, and it guesses the separator and the header for you, which makes it a good first attempt on a file whose format you do not yet know:
library(data.table)
df <- fread("data.csv")
One difference worth knowing: readr and data.table both keep text as text and only complain when a column cannot be parsed as the type they inferred, whereas base R is quieter about coercion. For a comparison of the same read in another language, see opening a CSV in Python.
The two imports that come back wrong
All columns in one. The file is not comma-separated. A European export where the comma is the decimal mark is usually semicolon-separated, so read.csv finds no commas and returns a single column. read.csv2 is the same function with sep = ";" and a decimal comma; equivalently, pass the separator by hand. This is the R version of the "opens in one column" symptom, and the delimiter is the cause in both.
df <- read.csv("export.csv", sep = ";", dec = ",")
Accented characters turn to garbage. The file is not UTF-8, or it is UTF-8 and R is reading it as the system encoding. State the encoding, and if the file carries a byte-order mark, let R handle it:
df <- read.csv("data.csv", fileEncoding = "UTF-8")
df <- read.csv("data.csv", fileEncoding = "UTF-8-BOM") # if a BOM is present
To find out which encoding you actually have before guessing, the Linux tools in opening a CSV in Linux (file -i) report it directly.
Reading a gzipped file, and other formats
R reads a compressed CSV without unpacking it first, as long as the connection is named correctly. read.csv and fread both accept a .gz path and decompress on the fly; with the base function you can also be explicit with gzfile:
df <- read.csv("data.csv.gz") # base R infers gzip from the name
df <- read.csv(gzfile("export.csv.gz")) # explicit connection
For tab-separated and other delimiters, read.delim and readr's read_delim do the same job with a different default separator. R has no built-in reader for the .xlsx binary format โ if the file is actually a spreadsheet, export a CSV copy first, which the CSV analyzer or the Excel-to-CSV converter can produce without Excel installed.
Files too large for memory
When a full read fails or exhausts RAM, read in chunks and process each piece. readr supports a chunk callback, and LaF is built for files larger than memory:
library(readr)
read_csv_chunked("big.csv", DataFrameCallback$new(function(chunk, pos) {
# summarise or filter here; only the result is kept
}), chunk_size = 100000)
If the same file will be read repeatedly, convert it once to parquet with arrow::write_parquet() and read that instead โ the text parse is the slow part, and you do it once. The row-count question that usually comes first is covered in counting rows in a CSV.
Frequently Asked Questions
How do I open a CSV file in R?
Use read.csv("data.csv") for a comma-separated file with a header, readr::read_csv for a tibble and a guessable column spec, or data.table::fread for the fastest large-file read. RStudio's File > Import Dataset writes the same call for you to copy.
Why did my CSV open as one column in R?
The separator is not a comma. Semicolon-separated files appear as one column. Use read.csv2() or read.csv("data.csv", sep = ";").
How do I keep leading zeros in R?
Force the column to text with colClasses = "character", or col_types = cols(.default = "c") in readr. Otherwise 01234 becomes 1234 as a number.
How do I read a large CSV in R?
Try fread() first for speed. If it does not fit in memory, read in chunks with readr or LaF, or convert the file to parquet once and read that.
NoCodeCSV Team
Updated October 9, 2026 ยท Practical guides by the NoCodeCSV team.
Go further with AI data tools
NoCodeCSV handles the basics for free. When your data work grows, these tools pair well with it:
- Stack AI โ build AI workflows that process your CSVs automatically, end to end. Try Stack AI
- Softr โ turn your cleaned data into customer-facing apps and portals without code. Try Softr
- Toggl Track โ track time spent on data projects and client work. Try Toggl
Some links above are affiliate links โ if you buy through them we may earn a commission at no extra cost to you.
Inspect a CSV Without a Script
Upload any CSV and read it as a clean table in seconds. No signup needed.
Related reading
CSV Fundamentals โ other guides that pair well with this one.
Browse all guides in the NoCodeCSV blog.