Writing output is essential for reproducible research!
Saving Plots: Quick Method
The easiest way - use ggsave() from ggplot2:
ggsave("My_most_recent_plot.pdf")
Saves your most recent ggplot to a file.
Saving Plots: RStudio Export Button
Within RStudio:
Go to the Plot window
Click Export
Choose format: PDF, PNG, JPG, etc.
Set size and resolution
Click Save
Quick and interactive!
When to Use Manual Methods
The Export button works great when:
You want a quick save
Making one or two plots
Interactively exploring
But… what if you need to:
Create a PDF with multiple pages?
Loop through subsets of data?
Generate many plots automatically?
You need programmatic control!
Using the pdf() Device
Create a PDF file programmatically:
pdf("Life_Exp_vs_time.pdf", width=12, height=4)# Your plotting code hereggplot(data=gapminder, aes(x=year, y=lifeExp, colour=country)) +geom_line() +theme(legend.position ="none")# Important: Turn off the PDF device!dev.off()
Understanding Devices
In R, a “device” is where your plot goes:
Screen device: Default (shows in Plot pane)
PDF device: Writes to PDF file
PNG device: Writes to PNG file
JPEG device: Writes to JPEG file
Other devices: SVG, BMP, TIFF, etc.
The pdf() Function
Parameters for control:
pdf("filename.pdf", width =12, # Width in inchesheight =4, # Height in inchespointsize =12, # Font sizefamily ="sans") # Font family
Creating Multi-Page PDFs
Each plotting command creates a new page:
pdf("multi_page.pdf", width=10, height=6)# Page 1plot(x =1:10, y =1:10)# Page 2plot(x =1:10, y = (1:10)^2)# Page 3plot(x =1:10, y =sqrt(1:10))dev.off() # Close the device
Each call to plot() adds a new page!
Important: dev.off()
Always remember to call dev.off()!
Closes the output device
Finalizes the file
Frees up the device
File won’t be complete without it
If you forget, the file is incomplete or corrupted!
Other Image Formats
Use similar functions for different formats:
png("plot.png", width=800, height=600)# Your plot codedev.off()jpeg("plot.jpg", width=800, height=600)# Your plot codedev.off()svg("plot.svg", width=10, height=8)# Your plot codedev.off()
Same structure, different output formats!
PNG and JPEG Parameters
For bitmap formats, use pixels for size:
png("plot.png", width=800, height=600, res=72)# res = resolution in DPI (dots per inch)jpeg("plot.jpg", width=800, height=600, quality=90)# quality = 0-100 (higher = better quality, larger file)
Challenge 1
Write a command to create a multi-page PDF showing:
Life expectancy vs. time (line plot) - first page
Same data with facets by continent (facet_grid) - second page
# Check if directory existsif (!dir.exists("cleaned-data")) {dir.create("cleaned-data")}# Then write your filewrite.csv(df, "cleaned-data/output.csv")
Prevents “directory not found” errors!
Best Practices for Output
Use descriptive filenames: gapminder-1990-onwards.csv
Include dates: results-2026-01-30.csv
Document transformations: Comment your code
Save intermediate steps: For debugging
Use consistent separators: CSV or TSV
Turn off row numbers: Unless needed
Quote only when needed: Smaller files
Combining Saving Plots and Data
Complete workflow:
# Subset datasubset_data <- gapminder[gapminder$year >=1990, ]# Create and save plotpdf("plot_recent.pdf")ggplot(subset_data, aes(x=year, y=lifeExp)) +geom_point()dev.off()# Save the subsetwrite.csv(subset_data, "recent-data.csv", row.names =FALSE)print("Analysis complete!")
Verification After Saving
Always verify your output:
# Read it back incheck_data <-read.csv("cleaned-data/gapminder-aus.csv")# Verify structurestr(check_data)head(check_data)# Compare with original (if needed)nrow(check_data) # Should match what we wrote
Common Mistakes
Forgetting to call dev.off() after plotting
Including row numbers when you don’t want them
Using wrong separators (comma vs tab)
Not creating output directories first
Forgetting quotes around filenames
Not verifying the output
File Naming Conventions
Good filenames:
gapminder-cleaned.csv
results_2026-01-30.csv
Africa_subset_1990-2007.csv
Bad filenames:
data.csv (too generic)
my file.csv (spaces problematic)
FINAL_FINAL_v3.csv (version chaos)
Be descriptive and version-controlled!
Performance Considerations
Writing large data frames:
# For large files, specify col.names and row.names explicitly# It's faster than letting R figure it outwrite.csv(large_df, "output.csv", row.names =FALSE,col.names =TRUE)
Can also use data.table::fwrite() for even faster writing.
Key Points
Save plots using pdf(), png(), or jpeg() devices
Always call dev.off() after saving plots
Use write.table() or write.csv() to save data
Set row.names = FALSE and quote = FALSE for clean CSV output