readr read_rds() in R: Load a Saved R Object
The readr read_rds() function loads a single saved R object from an .rds file back into your session. Unlike a CSV reader, it restores the exact object, so a data frame, a fitted model, or a list returns with all of its types and attributes intact.
read_rds("data.rds") # read a saved object
read_rds("https://site.com/obj.rds") # read straight from a URL
read_rds("nums.rds.gz") # gzip file, decompressed automatically
read_rds("model.rds") # restore a fitted model object
class(read_rds("data.rds")) # check what type came back
str(read_rds("data.rds")) # inspect structure on read
readRDS("data.rds") # base R equivalentNeed explanation? Read on for examples and pitfalls.
What read_rds() does
read_rds() restores one R object from an .rds file. An .rds file is a binary snapshot of a single object that write_rds() or base saveRDS() produced earlier. You give read_rds() the path to that file, and it hands the object back exactly as it was, whether the object is a tibble, a numeric vector, a nested list, or a fitted model.
This makes read_rds() the natural way to cache work between R sessions. A cleaned data frame or a slow-to-fit model can be saved once and reloaded instantly afterward. Because the file stores the object itself, nothing is re-parsed and no column types are guessed on the way back in.
Syntax and key arguments
The signature is tiny because the file already knows its own shape. There are no column types to guess and no delimiter to set. The object was serialized whole, so read_rds() only needs to know where the file lives.
You will pass file on almost every call and ignore refhook, which only matters for objects holding external pointers. The file argument accepts a local path, a connection, a URL, or a raw vector of bytes, so you can read an .rds file straight from the web.
Compression is detected automatically. A gzip, bzip2, or xz file reads with the same call as an uncompressed one, so you never pass a compression argument to read_rds() itself.
.rds workflow is the R counterpart of pickle. Where Python writes pickle.dump(obj, f) and reads pickle.load(f), R writes write_rds(obj, "obj.rds") and reads it back with read_rds("obj.rds").read_rds() examples
Start with a round trip. Write a built-in dataset to disk with write_rds(), then read it back so every example has a real file to work with.
The object returns as the same data.frame with all 32 rows. No CSV parsing happened, because the file stored the object itself rather than a text table. That is why an .rds read is faster and more predictable than re-importing a CSV.
read_rds() keeps exact R types. A CSV round trip flattens factors into text and dates into strings, so you must rebuild those types every time you reload. An .rds round trip does not, because it serializes the object with its classes attached.
The factor returns with its original levels, and the date column returns as a Date rather than character. This type fidelity is the main reason to choose .rds over CSV for intermediate results.
read_rds() restores any object, not just data frames. A fitted model is just another R object, so you can save one after a slow fit and read it back in a later session to skip refitting entirely.
The restored model is a complete lm object. You can call coef(), predict(), or summary() on it as if you had just fit it. Saving models this way is common in scoring scripts, where training and prediction run as separate jobs.
Compressed files read with the same call. Pass a compression option to write_rds(), and read_rds() decompresses the file transparently when you read it back.
The integer vector returns intact. Compression shrinks large .rds files noticeably for a little extra time, which is usually worth it for cached data.
read_rds() vs readRDS() and alternatives
read_rds() is the readr wrapper; readRDS() is base R. They read the same format and produce identical results, so the choice between them is about which API style the surrounding code already uses.
| Function | Reads | Objects | Format | Best for |
|---|---|---|---|---|
read_rds() |
one R object | single | binary, R only | readr-style restore of any object |
readRDS() |
one R object | single | binary, R only | base R scripts, identical result |
load() |
named objects | many | .RData / .rda |
restoring a whole workspace |
read_csv() |
a table | single | text, portable | tabular data shared across tools |
Use read_rds() inside tidyverse pipelines for an argument name (file) that matches the other readr functions. Use load() when a .RData file holds several named objects. Reach for read_csv() whenever the data must travel to another tool, since .rds is binary and R only. For very large objects, packages such as qs and fst read faster than read_rds().
.rds so reruns are instant. Export to CSV only when a person or another tool needs to read the data.Common pitfalls
Using read_rds() on a .RData file. A .RData or .rda file created with save() can hold many named objects at once, while read_rds() expects exactly one serialized object. Pointing read_rds() at such a file fails or returns something unusable. Use load("workspace.RData") instead, which restores each saved name directly into your environment rather than returning a single value.
Assuming the result is a data frame. read_rds() returns whatever object was written, which may be a list, a vector, or a model. Pipe it straight into data-frame code without checking and you get a confusing error. Call class() on the returned object first when unsure.
Expecting cross-language portability. An .rds file is R-specific binary serialization that Python, databases, and spreadsheet tools cannot open. When the data must leave R, export it as CSV or Parquet instead of .rds.
.rds files across machines, keep R versions reasonably close, or fall back to CSV for long-term archival.Try it yourself
Try it: Write the iris data frame to iris.rds, read it back into ex_iris, and confirm the Species column is still a factor. Save its class to ex_class.
Click to reveal solution
Explanation: read_rds() restores the exact object, so Species returns as a factor with its original levels. A CSV round trip would have read it back as plain character text instead.
Related readr functions
read_rds() sits among readr's import and export helpers. Reach for the one that matches the file you have.
write_rds(): write a single R object to an.rdsfile, the inverse of this function.read_csv(): read comma-separated text into a tibble.read_lines(): read a text file as a character vector, one element per line.read_file(): read a whole file into a single string.readRDS(): the base R equivalent that returns the same object.
For the full argument list, see the readr read_rds reference on tidyverse.org.
FAQ
What is the difference between read_rds() and readRDS() in R?
They return the same object from the same file. read_rds() comes from readr and names its first argument file, consistent with read_csv(). readRDS() is base R and names its argument con. Use whichever fits the surrounding code; there is no difference in the result or the file format.
What file type does read_rds() read?
read_rds() reads .rds files, a binary format that stores exactly one serialized R object, produced by write_rds() or base saveRDS(). It is not human readable and is specific to R, so it is best for caching results between R sessions rather than sharing data widely.
Can read_rds() read an .RData file?
No. A .RData or .rda file made with save() can hold many named objects, while read_rds() expects a single object. Use load("file.RData") for those files; it restores each saved name into your environment instead of returning a value.
Does read_rds() preserve factors and dates?
Yes. Because an .rds file stores the object itself, read_rds() returns factors, dates, list columns, and custom attributes exactly as written. This is the main advantage over a CSV round trip, which flattens those types into plain text.
How do I read a compressed .rds file?
Just call read_rds("file.rds.gz"). read_rds() detects gzip, bzip2, and xz compression automatically and decompresses the file before deserializing it. You pass no compression argument when reading; that choice is made only when the file is written.