Skip to Content
Course content

172: Reading and Writing Parquet Files in R

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen this happen in almost every production environment I've touched: a developer starts a project using CSVs because they're easy to peek at in a text editor. Everything works fine when the dataset is 10,000 rows. But then the project scales to 10 million rows, and suddenly, the "simple" data loading step takes five minutes, the server runs out of RAM, and you spend half your morning fixing column types that shifted from integers to doubles during the save-and-load cycle.

The CSV Trap: Why your disk is screaming

If you're still using write.csv() and read.csv() for large datasets, you're fighting a losing battle. Let's say we're working with a massive dataset of global weather sensor readings—millions of rows with timestamps, sensor IDs, and temperature readings. In the naive approach, you'd do something like this:

# The slow, memory-heavy way
write.csv(weather_data, "weather_readings.csv", row.names = FALSE)
# Later...
weather_data <- read.csv("weather_readings.csv")

Here is the problem: CSVs are plain text. Every single number is stored as a string of characters. To R, the number 23.456789 isn't a double; it's eight separate characters. This bloats your file size and forces R to "guess" the data types every time you read the file back in. I can't tell you how many bugs I've chased down because a column of IDs was read as numeric instead of character, causing leading zeros to vanish into thin air.

Switching to Parquet for Actual Performance

This is where Parquet comes in. Unlike CSVs, Parquet is a columnar storage format. Instead of storing data row-by-row, it stores it column-by-column and compresses it heavily. For our weather data, this is a game-changer. If you only need the temperature column, Parquet allows the system to skip over the sensor_id and timestamp columns entirely on the disk.

To do this in R, we use the arrow package. It's the industry standard for handling this format. Here is how I would handle that same weather dataset:

library(arrow)

# Writing the data - this is significantly faster and the file is tiny
write_parquet(weather_data, "weather_readings.parquet")

# Reading the data - types are preserved exactly as they were
weather_data <- read_parquet("weather_readings.parquet")

When you run this, you'll notice two things immediately. First, the file size on your hard drive will plummet—often by 70% to 90% compared to a CSV. Second, the loading time is almost instantaneous. More importantly, the schema is baked into the file. Your dates stay dates, your integers stay integers, and you don't have to pass colClasses to read.csv just to keep your data from breaking.

The Trade-off: Readability vs. Efficiency

Now, I'm not telling you to delete every CSV you own. Parquet is a binary format; you can't open it in Notepad or TextEdit to see if "the data looks right." It's an opaque blob to a human.

If you're exporting a small summary table for a non-technical stakeholder to open in Excel, stick with CSV. It's the universal language of spreadsheets. But for any internal data pipeline, intermediate storage between scripts, or datasets that exceed a few hundred megabytes, Parquet is the only professional choice. I generally follow a simple rule: if the file is for a human, CSV; if the file is for a machine, Parquet.




📋 Practical Task

Exercise: Optimizing the Sensor Archive

You have been handed a legacy dataset containing 1 million simulated sensor readings. Your goal is to prove the efficiency of Parquet over CSV by comparing their footprints and loading speeds.

Requirements:

  • Create a dataframe called sensor_logs with 1,000,000 rows. It should have three columns: timestamp (POSIXct), sensor_id (a factor or character), and value (numeric).
  • Write this dataframe to a file named logs.csv and then to a file named logs.parquet using the arrow package.
  • Use file.info()$size to compare the file sizes of the two resulting files and print the difference.
  • Use system.time() to measure how long it takes to read the CSV back into R versus reading the Parquet file.
  • Verify that the timestamp column in the Parquet-loaded dataframe is still a POSIXct object, whereas the CSV-loaded version requires conversion.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.