Learning Objectives
- load external data (CSV files) in memory using the survey table (
surveys.csv
) as an example- explore the structure and the content of the data in R
- understand what are factors and how to manipulate them
We are studying the species and weight of animals caught in plots in our study area. The dataset is stored as a .csv
file: each row holds information for a single animal, and the columns represent survey_id
, month
, day
, year
, plot
, species
(a 2 letter code, see the species.csv
file for correspondance), sex
(“M” for males and “F” for females), wgt
(the weight in grams).
The first few rows of the survey dataset look like this:
"63","8","19","1977","3","DM","M","40"
"64","8","19","1977","7","DM","M","48"
"65","8","19","1977","4","DM","F","29"
"66","8","19","1977","4","DM","F","46"
"67","8","19","1977","7","DM","M","36"
To load our survey data, we need to locate the surveys.csv
file. We will use read.csv()
to load into memory (as a data.frame
) the content of the CSV file.
"data"
within your working directory for these exercisessurveys <- read.csv('data/surveys.csv')
This statement doesn’t produce any output because assignment doesn’t display anything. If we want to check that our data has been loaded, we can print the variable’s value: surveys
Wow… that was a lot of output. At least it means the data loaded properly. Let’s check the top (the first 6 lines) of this data.frame
using the function head()
:
head(surveys)
## record_id month day year plot species sex wgt
## 1 1 7 16 1977 2 NL M NA
## 2 2 7 16 1977 3 NL M NA
## 3 3 7 16 1977 2 DM F NA
## 4 4 7 16 1977 7 DM M NA
## 5 5 7 16 1977 3 DM M NA
## 6 6 7 16 1977 1 PF M NA
Let’s now check the structure of this data.frame
in more details with the function str()
:
str(surveys)
Read in another CSV file, species.csv
, and store it in a variable.
Based on the output of str(surveys)
, can you answer the following questions?
surveys
?species
?As you can see, the columns species
and sex
are of a special class called factor
. Before we learn more about the data.frame
class, we are going to talk about factors. They are very useful but not necessarily intuitive, and therefore require some attention. We will talk about data frames in more detail in the next lesson.
Factors are used to represent categorical data. Factors can be ordered or unordered and are an important class for statistical analysis and for plotting.
Factors are stored as integers, and have labels associated with these unique integers. While factors look (and often behave) like character vectors, they are actually integers under the hood, and you need to be careful when treating them like strings.
Once created, factors can only contain a pre-defined set values, known as levels. By default, R always sorts levels in alphabetical order. For instance, if you have a factor with 2 levels:
sex <- factor(c("male", "female", "female", "male"))
R will assign 1
to the level "female"
and 2
to the level "male"
(because f
comes before m
, even though the first element in this vector is "male"
). You can check this by using the function levels()
, and check the number of levels using nlevels()
:
levels(sex)
nlevels(sex)
Sometimes, the order of the factors does not matter, other times you might want to specify the order because it is meaningful (e.g., “low”, “medium”, “high”) or it is required by particular type of analysis. Additionally, specifying the order of the levels allows to compare levels:
food <- factor(c("low", "high", "medium", "high", "low", "medium", "high"))
levels(food)
food <- factor(food, levels=c("low", "medium", "high"))
levels(food)
min(food) ## doesn't work
## Error: min not meaningful for factors
food <- factor(food, levels=c("low", "medium", "high"), ordered=TRUE)
levels(food)
min(food) ## works!
In R’s memory, these factors are represented by numbers (1, 2, 3). They are better than using simple integer labels because factors are self describing: "low"
, "medium"
, and "high"
is more descriptive than 1
, 2
, 3
. Which is low? You wouldn’t be able to tell with just integer data. Factors have this information built in. It is particularly helpful when there are many levels (like the species in our example data set).
If you need to convert a factor to a character vector, simply use as.character(x)
.
Converting a factor to a numeric vector is however a little trickier, and you have to go via a character vector. Compare:
f <- factor(c(1, 5, 10, 2))
as.numeric(f) ## wrong! and there is no warning...
as.numeric(as.character(f)) ## works...
as.numeric(levels(f))[f] ## The recommended way.
R has a built-in function called sort()
, for sorting data.
We can make a vector of factors and then sort it like this:
sizes = factor(c("large","small","small","medium","large","large"));
sort(sizes);
## [1] large large large medium small small
## Levels: large medium small
Unfortunately it looks like our vector has been sorted in the order large, medium, small. How could we use an ordered factor make sure it sorts in the order small, medium, large?
Previous: Introduction to R Next: Data Frames