stations <- c("CT01", "CT02", "CT03")
detections <- c(12, 5, 8)Module 4: Importing and Exporting Data
Introduction
So far, we have created all of our objects directly inside R.
For example:
But this is not how we normally work with real datasets.
Most of the time, our data already exist in a file created in Excel, Google Sheets, field-data software, or another program.
One of the most important skills when learning R is therefore knowing how to bring external data into R.
In this module we will learn how to:
- understand where R looks for files,
- organize data inside an RStudio Project,
- import
.csvfiles, - import Excel files,
- inspect imported data,
- and export data from R.
Let’s get started
Open your intro-r-course project and create a new R script.
Save it inside the scripts folder as:
module-04.R
Remember that our project should look approximately like this:
intro-r-course/
│
├── data/
├── scripts/
│ └── module-04.R
├── outputs/
└── intro-r-course.Rproj
Throughout this module, the files we want to import will be stored inside:
data/
Where is R looking for files?
Before importing a file, R needs to know where the file is located.
The folder that R currently considers its starting location is called the working directory.
We can check it using:
getwd()[1] "C:/Users/andradegp/AppData/Local/Temp/RtmpW8fHyP/file85a434ae5f2c/modules"
Because we are working inside an RStudio Project, the working directory should normally be the main folder of our project:
intro-r-course/
This is one of the main reasons we created an RStudio Project at the beginning of the course.
setwd() inside your scripts
You may see tutorials that use:
setwd("C:/Users/YourName/Documents/MyProject")to specify the working directory.
This may work on your computer, but that path will probably not work on someone else’s computer.
Using an RStudio Project allows us to avoid this problem and work with relative paths instead.
File paths
A file path tells R where a file is located.
There are two general types of paths:
- absolute paths,
- relative paths.
Absolute paths
An absolute path describes the complete location of a file on your computer.
For example:
C:/Users/Gabriel/Documents/intro-r-course/data/camera_data.csv
This may work perfectly on one computer.
But if we send the project to another person, their computer probably does not have:
C:/Users/Gabriel/
So the code will no longer work.
Relative paths
A relative path describes the location of a file relative to our project folder.
If our file is stored here:
intro-r-course/
│
├── data/
│ └── camera_data.csv
│
├── scripts/
└── outputs/
we can refer to it simply as:
data/camera_data.csv
This is much more portable.
If we move the entire project to another computer, the internal structure remains the same.
A simple project structure such as:
project/
├── data/
├── scripts/
└── outputs/
makes file paths much easier to understand and helps keep your analyses reproducible.
What is a CSV file?
One of the most common formats for storing tabular data is CSV.
CSV stands for:
Comma-Separated Values
A CSV file is essentially a plain-text table.
For example, a spreadsheet that looks like this:
| station | species | detections | camera_days |
|---|---|---|---|
| CT01 | Raccoon | 12 | 30 |
| CT02 | Coyote | 5 | 28 |
| CT03 | Bobcat | 8 | 30 |
may be stored internally as:
station,species,detections,camera_days
CT01,Raccoon,12,30
CT02,Coyote,5,28
CT03,Bobcat,8,30
Because CSV files are simple text files, they can be opened by many different programs, including:
- Excel,
- Google Sheets,
- R,
- Python,
- text editors,
- and many other programs.
This makes CSV a very useful format for sharing and analyzing data.
From Excel to CSV
Many datasets begin their life in Excel.
That is completely fine.
However, when we begin analyzing the data in R, it is often useful to save a copy as a CSV file.
In Excel:
File → Save As
and select:
CSV (Comma delimited) (*.csv)
Save the file inside the data folder of your RStudio Project.
For example:
data/camera_data.csv
Do not replace or modify your only copy of the original dataset.
A good workflow is to keep the original file unchanged and create a separate CSV file for analysis.
For example:
data/
├── camera_data_original.xlsx
└── camera_data.csv
Importing a CSV file
Base R includes the function:
read.csv()
which reads a CSV file and converts it into a data frame.
If our file is located here:
data/camera_data.csv
we can import it using:
camera_data <- read.csv("data/camera_data.csv")There are two important things happening here.
First:
read.csv("data/camera_data.csv")reads the file.
Second:
camera_data <-stores the imported dataset in an R object called camera_data.
If we forget the assignment:
read.csv("data/camera_data.csv") species n_events n_stations
1 Armadillo 33 6
2 Bird 20 3
3 Black vulture 23 2
4 Bobcat 3 2
5 Coyote 37 2
6 Eastern gray squirrel 1 1
7 Fox squirrel 3 2
8 Gray fox 9 2
9 Hog 9 4
10 Human 18 12
11 Raccoon 35 5
12 Turkey vulture 53 4
13 Virginia opossum 23 3
14 White-tailed deer 104 7
R can still read and display the file, but we have not saved it as an object that we can continue working with.
Check that the data loaded correctly
Importing a file without an error does not necessarily mean that everything was read correctly.
We should always inspect the data after importing it.
For example:
head(camera_data) species n_events n_stations
1 Armadillo 33 6
2 Bird 20 3
3 Black vulture 23 2
4 Bobcat 3 2
5 Coyote 37 2
6 Eastern gray squirrel 1 1
str(camera_data)'data.frame': 14 obs. of 3 variables:
$ species : chr "Armadillo" "Bird" "Black vulture" "Bobcat" ...
$ n_events : int 33 20 23 3 37 1 3 9 9 18 ...
$ n_stations: int 6 3 2 2 2 1 2 2 4 12 ...
dim(camera_data)[1] 14 3
names(camera_data)[1] "species" "n_events" "n_stations"
These functions should already look familiar from the previous module.
We can also open the dataset using RStudio’s data viewer:
View(camera_data)After importing a dataset, ask yourself:
- Does it have the expected number of rows?
- Does it have the expected number of columns?
- Are the column names correct?
- Are numeric columns actually numeric?
- Did missing values import correctly?
- Does the dataset look like the file I expected to load?
Never assume that a file was imported correctly just because R did not return an error.
Common CSV problems
Files do not always import exactly as expected.
A few common problems include:
Wrong file name
For example:
read.csv("data/camera-data.csv")will not work if the actual file is called:
camera_data.csv
The names must match.
Wrong folder
This:
read.csv("camera_data.csv")tells R to look for the file directly inside the project folder.
But if the file is inside:
data/
we need:
read.csv("data/camera_data.csv")Capitalization
Depending on the operating system:
Camera_Data.csv
and:
camera_data.csv
may be treated as different file names.
Consistent file names help avoid these problems.
Does the file exist?
If R tells you that it cannot find a file, we can check whether R can see it.
For example:
file.exists("data/camera_data.csv")[1] TRUE
If R returns:
TRUE
the file exists at that location.
If R returns:
FALSE
something about the path or file name is incorrect.
We can also see the files inside our data folder:
list.files("data")[1] "camera_data.csv" "camera_data.xlsx" "recordTable.csv"
These two functions can be extremely useful when troubleshooting import problems.
Importing CSV files with readr
There are several ways to import the same type of file in R.
The tidyverse includes a package called readr that provides another function for reading CSV files:
read_csv()
Because we installed tidyverse at the beginning of the course, we can load it using:
library(tidyverse)── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Then:
camera_data2 <- read_csv("data/camera_data.csv")Notice the difference:
Base R read.csv()
readr read_csv()
Both functions can read CSV files.
For this course, you may see both, but later we will frequently use read_csv() because it works naturally with other tidyverse tools.
You do not need to memorize multiple ways to import the same file.
What matters is understanding:
- where the file is,
- what type of file it is,
- which function can read it,
- and what object will store the result.
Importing Excel files
Sometimes we want to import an Excel file directly instead of converting it to CSV.
Base R does not include a function for reading .xlsx files, so we need an additional package.
We installed readxl during the Getting Started section.
Load it using:
library(readxl)Then we can import an Excel file using:
camera_data3 <- read_excel( "data/camera_data.xlsx")The function is called:
read_excel()
and comes from the readxl package.
Excel files with multiple sheets
An Excel workbook can contain several sheets.
We can see their names using:
excel_sheets("data/camera_data.xlsx")[1] "camera_records" "secret_tab"
If the workbook contains a sheet called:
camera_records
we can import that specific sheet using:
camera_data3 <- read_excel("data/camera_data.xlsx",
sheet = "camera_records"
)We can also select a sheet by position:
camera_data3 <- read_excel(
"data/camera_data.xlsx",
sheet = 1
)CSV or Excel?
Both formats can be useful.
CSV
Advantages:
- simple,
- open format,
- easy to share,
- readable by almost any software,
- good for analysis and reproducibility.
Limitations:
- only stores one table,
- does not preserve formatting,
- does not store formulas or multiple sheets.
Excel
Advantages:
- familiar to many users,
- can contain multiple sheets,
- useful for entering and reviewing data.
Limitations:
- more complex file format,
- formatting can sometimes hide data problems,
- spreadsheet software may automatically modify dates or other values.
A common workflow is:
Enter/review data in Excel → save a clean CSV → analyze the CSV in R
But R can work directly with either format.
Importing data using RStudio
RStudio also provides a graphical interface for importing datasets.
In the Environment panel, select:
Import Dataset
RStudio will provide options for importing text and Excel files.
This can be useful when you are learning because RStudio shows a preview of the data and generates the corresponding R code.
However, once you understand the import function, it is better to keep the import command inside your script.
For example:
camera_data <- read_csv(
"data/camera_data.csv"
)This way, the analysis can be reproduced later without manually clicking through menus.
The graphical import tool is useful for learning.
But try to copy the generated code into your script so that you can reproduce the import later.
File names and column names
Good file organization begins before we import anything into R.
Try to use simple and consistent file names.
Instead of:
Camera Data FINAL version 2 updated!!!.xlsx
use something like:
camera_data.xlsx
or:
camera_data_2026.xlsx
The same principle applies to column names.
Instead of:
Camera Station
Number of detections
Habitat Type
consider:
station
detections
habitat
or:
camera_station
number_of_detections
habitat_type
Consistent names make working with data in R much easier.
Exporting data
Sometimes we want to save a dataset after modifying or summarizing it in R.
For CSV files, base R provides:
write.csv()
For example:
write.csv(
camera_data,
"outputs/camera_data_clean.csv",
row.names = FALSE
)This creates:
outputs/camera_data_clean.csv
We use:
row.names = FALSE
because otherwise base R will add an extra column containing the row numbers.
Exporting with readr
If we are using the tidyverse, we can also use:
write_csv(
camera_data,
"outputs/camera_data_clean.csv"
)write_csv() does not add row names by default.
Again, you do not need to memorize every alternative.
The important idea is:
read → bring data into R
write → save data from R
Keep raw data separate from outputs
Remember our project structure:
intro-r-course/
│
├── data/
├── scripts/
└── outputs/
A useful rule is:
data/
contains the original data that we received or collected.
outputs/
contains files created by our analysis.
For example:
intro-r-course/
│
├── data/
│ └── camera_data.csv
│
├── scripts/
│ └── module-04.R
│
└── outputs/
└── camera_data_clean.csv
Try not to overwrite your original data from R.
Keeping the raw data unchanged means that you can always return to the original information and reproduce every change using your script.
Practice at home
This activity should take approximately 15–20 minutes.
Open your intro-r-course project and create a new script called:
practice-04.R
Save it inside the scripts folder.
Use any small Excel dataset you have available, or create one with at least:
- 5 rows,
- 3 columns,
- one column containing text,
- one column containing numbers.
For example:
| station | habitat | detections |
|---|---|---|
| CT01 | Forest | 8 |
| CT02 | Pasture | 3 |
| CT03 | Forest | 12 |
| CT04 | Pasture | 0 |
| CT05 | Forest | 5 |
Part 1: Prepare the data
- Save the Excel file inside your project’s
datafolder. - Save a second copy as a
.csvfile.
Your folder should contain something like:
data/
├── practice_data.xlsx
└── practice_data.csv
Part 2: Import the CSV
Import the CSV file into an object called:
practice_data
Then use:
head()
str()
dim()
names()to inspect the imported dataset.
Part 3: Import the Excel file
Load the readxl package and import the Excel version of the same dataset.
Save it as:
practice_excel
Compare:
class(practice_data)
class(practice_excel)and inspect both objects.
Part 4: Export the data
Export practice_data into the outputs folder with the name:
practice_data_exported.csv
Finally, check that the new file appears inside the outputs folder.
# Practice for Module 4
# ---------------------------
# Import CSV
# ---------------------------
practice_data <- read.csv(
"data/practice_data.csv"
)
# Inspect the data
head(practice_data)
str(practice_data)
dim(practice_data)
names(practice_data)
# ---------------------------
# Import Excel
# ---------------------------
library(readxl)
practice_excel <- read_excel(
"data/practice_data.xlsx"
)
# Inspect the Excel data
head(practice_excel)
str(practice_excel)
# Compare classes
class(practice_data)
class(practice_excel)
# ---------------------------
# Export data
# ---------------------------
write.csv(
practice_data,
"outputs/practice_data_exported.csv",
row.names = FALSE
)The important thing is that you understand the complete workflow:
external file
↓
relative path
↓
read the file
↓
store it as an R object
↓
inspect the object
↓
work with the data
↓
write an output file