x <- c(0.5, 0.6)
class(x) [1] "numeric"
A vector is the most convenient way to store more than one data value.
A vector is a contiguous cell that contains data, where each cell can be accessed by an index. In other words, a vector is an indexed set of objects.
All the elements of an atomic vector have to be of the same type —numeric, character, or logical— which is called the mode of the vector.
There are many ways to create a vector, but these are four basic functions for constructing vectors:
The c() (combine) function can be used to create vectors of objects by concatenating things together.
Examples:
x <- c(0.5, 0.6)
class(x) [1] "numeric"
x <- c(TRUE, FALSE)
class(x) [1] "logical"
x <- c(T, F)
class(x) [1] "logical"
x <- c("a", "b", "c")
class(x) [1] "character"
x <- 9:29
class(x) [1] "integer"
x <- c(1+0i, 2+4i)
class(x) [1] "complex"
seq(from, to, by):
(x <- seq(1, 20, 2)) [1] 1 3 5 7 9 11 13 15 17 19
rep(x, times):
(y <- rep(3, 4))[1] 3 3 3 3
You can also use the vector() function to initialize vectors:
Example:
x <- vector("numeric", length = 10)
class(x) [1] "numeric"
Example:
x[4] <- 9# Create a vector with the name of each element
named.num.vec <- c(x1=1, x2=3, x3=5)
named.num.vec x1 x2 x3
1 3 5
This is another option to add names:
names(x) <- c("a", "b", "c)The function length(x) gives the number of elements of ‘x’.
x <- 100:100
length(x)[1] 1
It is possible to have a vector with no elements
x <- c()
length(x)[1] 0
Statisticians typically recognise three basic types of variable: numeric, ordinal, and categorical. In R the data type for ordinal and categorical vectors is factor. The possible values of a factor are referred to as its levels.
In practice, a factor is not much different from a character vector, except that the elements of a factor can take only a limited number of values (of which R keeps a record), and in statistical routines R is able to treat a factor differently than a character vector.
To create a factor we apply the function factor() to some vector x. By default the distinct values of x become the levels, or we can specify them using the optional levels argument.
Example:
x <- factor(c("yes", "yes", "no", "yes", "no"))
table(x)x
no yes
2 3
levels(x)[1] "no" "yes"
Note the use of the function table() to calculate the number of times each level of the factor appears. table() can be applied to other modes of vectors as well as factors. The output of the table() function is a one-dimensional array (as opposed to a vector). If more than one vector is passed to table(), then it produces a multidimensional array.
The order of the levels of a factor can be set using the levels argument to factor(). By default R arranges the levels of a factor alphabetically. If you specify the levels yourself, then R uses the ordering that you provide.
Example:
x <- factor(c("yes", "yes", "no", "yes", "no"), levels = c("yes", "no"), ordered=TRUE)
x[1] yes yes no yes no
Levels: yes < no
Using factors with labels is better than using integers because factors are self-describing.
Example:
phys.act <- factor(phys.act, levels = c("L", "M", "H"),
labels = c("Low", "Medium", "High"),
ordered = TRUE)We check whether or not an object x is a factor using is.factor(x).
Example:
is.factor(x)[1] TRUE
Usually it is convenient to transform a numeric variable into a data.frame:
airquality <- transform(airquality, Month = factor(Month))cut() is a generic command to create factor variables from numeric variables:
Example:
numvar <- rnorm(100)
num2factor <- cut(numvar, breaks=5) ## the levels are produced using the actual range of values
num2factor [1] (0.738,1.58] (-0.0954,0.738] (-0.929,-0.0954] (-0.0954,0.738]
[5] (-1.76,-0.929] (-1.76,-0.929] (0.738,1.58] (-0.929,-0.0954]
[9] (-1.76,-0.929] (0.738,1.58] (-0.929,-0.0954] (-0.0954,0.738]
[13] (-0.929,-0.0954] (-0.0954,0.738] (-0.929,-0.0954] (0.738,1.58]
[17] (0.738,1.58] (-1.76,-0.929] (-0.929,-0.0954] (0.738,1.58]
[21] (-0.929,-0.0954] (-2.6,-1.76] (-0.0954,0.738] (-0.0954,0.738]
[25] (0.738,1.58] (-0.0954,0.738] (-2.6,-1.76] (-0.929,-0.0954]
[29] (-0.929,-0.0954] (-0.0954,0.738] (-0.929,-0.0954] (-0.929,-0.0954]
[33] (-0.929,-0.0954] (0.738,1.58] (-0.929,-0.0954] (-1.76,-0.929]
[37] (-1.76,-0.929] (-0.0954,0.738] (-0.929,-0.0954] (-0.929,-0.0954]
[41] (-0.929,-0.0954] (-0.929,-0.0954] (-0.929,-0.0954] (0.738,1.58]
[45] (0.738,1.58] (-0.0954,0.738] (-0.929,-0.0954] (0.738,1.58]
[49] (-0.0954,0.738] (-0.929,-0.0954] (0.738,1.58] (-0.929,-0.0954]
[53] (-0.0954,0.738] (-0.0954,0.738] (-0.0954,0.738] (-0.929,-0.0954]
[57] (-0.929,-0.0954] (-1.76,-0.929] (-1.76,-0.929] (-0.929,-0.0954]
[61] (-0.0954,0.738] (-0.0954,0.738] (-0.0954,0.738] (-0.0954,0.738]
[65] (-0.0954,0.738] (-0.0954,0.738] (-0.0954,0.738] (0.738,1.58]
[69] (0.738,1.58] (0.738,1.58] (-0.0954,0.738] (0.738,1.58]
[73] (-0.929,-0.0954] (-0.929,-0.0954] (-0.0954,0.738] (-2.6,-1.76]
[77] (-1.76,-0.929] (-0.0954,0.738] (0.738,1.58] (0.738,1.58]
[81] (0.738,1.58] (0.738,1.58] (-0.0954,0.738] (-1.76,-0.929]
[85] (0.738,1.58] (-1.76,-0.929] (-0.929,-0.0954] (-0.0954,0.738]
[89] (-1.76,-0.929] (-0.929,-0.0954] (-0.929,-0.0954] (-0.929,-0.0954]
[93] (-0.929,-0.0954] (-1.76,-0.929] (-0.0954,0.738] (-0.0954,0.738]
[97] (-0.0954,0.738] (-1.76,-0.929] (-2.6,-1.76] (-0.929,-0.0954]
5 Levels: (-2.6,-1.76] (-1.76,-0.929] (-0.929,-0.0954] ... (0.738,1.58]
num2factor <- cut(numvar, breaks=5, labels= c("lowest group", "lower middle group", "middle group", "upper middle", "highest group"))
data.frame(table(num2factor)) ## displaying the data in tabular form num2factor Freq
1 lowest group 4
2 lower middle group 14
3 middle group 32
4 upper middle 29
5 highest group 21
Matrices are stored as vectors with an added dimension attribute. The dimension attribute is itself an integer vector of length 2, which gives the number of rows and columns.
The matrix elements are stored column-wise in the vector. This means that it is possible to access the matrix elements using a single index:
(A <- matrix(c(3,5,2,3), 2, 2)) [,1] [,2]
[1,] 3 2
[2,] 5 3
A[2][1] 5
A[,2][1] 2 3
Matrices are constructed column-wise, so entries can be thought of starting in the “upper left” corner and running down the columns.
Example:
(m <- matrix(1:6, nrow = 2, ncol = 3, byrow = FALSE)) [,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
dim(m) [1] 2 3
Matrices can be created by column-binding or row-binding with the cbind() and rbind() functions:
Examples:
x <- 1:3
y <- 10:12
cbind(x, y) x y
[1,] 1 10
[2,] 2 11
[3,] 3 12
rbind(x, y) [,1] [,2] [,3]
x 1 2 3
y 10 11 12
Matrices can also be created directly from vectors by adding a dimension attribute:
Example:
m <- 1:10
dim(m) <- c(2, 5)
m [,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
To create a matrixA with one column from a vector x, we use:
A <- as.matrix(x)To create a vector from a matrix A, we use:
x <- as.vector(A)To create a diagonal matrix use diag(x):
B <- diag(c(1,2,3))Matrices can have names:
Example:
dimnames(m) <- list(c("a", "b"), c("c", "d", "e"))
mThese are other options for column and row names:
colnames(m) <- c("c", "d", "e")rownames(m) <- c("a", "b")To perform matrix multiplication we use the operator %*%. Remember that * acts element wise on matrices.
Other functions for using with matrices are:
nrow(x)ncol(x)det(x) (the determinant)t(x) (the transpose)solve(A, B) (returns x such that A %*% x == B).It is a list of vectors restricted to be of equal length. Each vector —or column— corresponds to a variable in an experiment, and each row corresponds to a single observation or experimental unit. Each vector can be of any of the basic modes of object.
The dataframe is like a matrix but extended to allow for different object modes in different columns. Unlike matrices, data frames can store different classes of objects in each column (matrices must have every element be the same class, e.g. all integers or all numeric). Obviously to work with datasets from real experiments we need a way to group data of differing modes.
Data frames are used to store tabular data in R. Data frames are represented as a special type of list where every element of the list has to have the same length. Each element of the list can be thought of as a column and the length of each element of the list is the number of rows.
Data frames are usually created by:
reading in a dataset using the read.table() or read.csv()
creating a dataframe with data.frame():
Example:
(x <- data.frame(foo = 1:4, bar = c(T, T, F, F))) foo bar
1 1 TRUE
2 2 TRUE
3 3 FALSE
4 4 FALSE
# To summarise the structure of a list (or dataframe), use str()
str(x)'data.frame': 4 obs. of 2 variables:
$ foo: int 1 2 3 4
$ bar: logi TRUE TRUE FALSE FALSE
coerced from other types of objects like lists:
x <- as.data.frame(x)Dataframes can be converted to a matrix by calling data.matrix().
The dplyr package has an optimized set of functions designed to work efficiently with dataframes.
You can construct a dataframe from a collection of vectors and/or existing dataframes using the function data.frame, which has the form: data.frame(col1 = x1, col2 = x2, ..., df1, df2, ...). Here col1, col2, etc., are the column names (given as character strings without quotes) and x1, x2, etc., are vectors of equal length. df1, df2, etc., are dataframes, whose columns must be the same length as the vectors x1, x2, etc. Column names may be omitted, in which case R will choose a name for you.
Column names indicate the names of the variables or predictors names(). We can also create a new variable within a dataframe, by naming it and assigning it a value:
Example:
ufc$volume.m3 <- pi * (ufc$dbh.cm / 200)^2 * ufc$height.m / 2Equivalently one could assign to ufc[6] or ufc["volume.m3"] or ufc[[6]] or ufc[["volume.m3"]].
The command names(df) will return the names of the dataframe df as a vector of character strings.
Example:
ufc.names <- names(ufc)
# To change the names of df you pass a vector of character strings to `names(df)`
names(ufc) <- c("P", "T", "S", "D", "H", "V")When you create dataframes and any one of the column’s classes is a character, it automatically gets converted to factor, which is a default R operation. However, there is one argument, stringsAsFactors=FALSE, that allows us to prevent the automatic conversion of character to factor during data frame creation.
Dataframes have a special attribute called row.names() which indicate information about each row of the data frame. You can change the row names of df by making an assignment to row.names(df).
subset()The function subset() is a convenient tool for selecting the rows of a dataframe, especially when combined with the operator %in%.
Example:
# Suppose you are only interested in the height of trees of species DF (Douglas Fir) or GF (Grand Fir)
fir.height <- subset(ufc, subset = species %in% c("DF", "GF"),
select = c(plot, tree, height.m))
head(fir.height)attach()R allows you to attach a dataframe to the workspace. When attached, the variables in the dataframe can be referred to without being prefixed by the name of the dataframe.
Example:
attach(ufc)
max(height.m[species == "GF"])When you attach a dataframe R actually makes a copy of each variable, which is deleted when the dataframe is detached. Thus, if you change an attached variable you do not change the dataframe. After we use the attach() command, we need to use detach() to remove individual variables from the working environment.
Nonetheless, note that the with() and transform()functions provide a safer alternative.
Lists are a special type of vector that can contain elements of different type (we can store single constants, vectors of numeric values, factors, data frames, matrices, and even arrays), namely, a list is a general data storage object that can house pretty much any other kind of R object.
Like a vector, a list is an indexed set of objects (and so has a length), but unlike a vector the elements of a list can be of different types, including other lists! The mode of a list is list.
The power and utility of lists comes from this generality. A list might contain an individual measurement, a vector of observations on a single response variable, a dataframe, or even a list of dataframes containing the results of several experiments.
In R lists are often used for collecting and storing complicated function output. Dataframes are special kinds of lists.
Lists can be explicitly created using the list() function, which takes an arbitrary number of arguments:
Example 1:
(x <- list(1, "a", TRUE, 1 + 4i))[[1]]
[1] 1
[[2]]
[1] "a"
[[3]]
[1] TRUE
[[4]]
[1] 1+4i
Example 2:
(my.list <- list("one", TRUE, 3, c("f","o","u","r")))[[1]]
[1] "one"
[[2]]
[1] TRUE
[[3]]
[1] 3
[[4]]
[1] "f" "o" "u" "r"
my.list[[2]][1] TRUE
mode(my.list[[2]])[1] "logical"
my.list[[4]][1][1] "f"
my.list[4][1][[1]]
[1] "f" "o" "u" "r"
We can also create an empty list of a pre-specified length with the vector() function:
Example:
(x <- vector(mode = "list", length = 5)) # the elements are NULL[[1]]
NULL
[[2]]
NULL
[[3]]
NULL
[[4]]
NULL
[[5]]
NULL
To flatten a list x, that is convert it to a vector, we use unlist(x).
Example:
x <- list(1, c(2, 3), c(4, 5, 6))
unlist(x)[1] 1 2 3 4 5 6
Many functions produce list objects as their output. For example, when we fit a least squares regression, the regression object itself is a list, and can be manipulated using list operations.
Example:
lm.xy <- lm(y ~ x, data = data.frame(x = 1:5, y = 1:5))
mode(lm.xy)[1] "list"
names(lm.xy) [1] "coefficients" "residuals" "effects" "rank"
[5] "fitted.values" "assign" "qr" "df.residual"
[9] "xlevels" "call" "terms" "model"
The elements of a list can be named when the list is created, using arguments of the form name1 = x1, name2 = x2, etc., or they can be named later by assigning a value to the names attribute.
Example:
my.list <- list(first = "one", second = TRUE, third = 3,
fourth = c("f","o","u","r"))
names(my.list)[1] "first" "second" "third" "fourth"
Unlike a dataframe, the elements of a list do not have to be named. Names can be used (within quotes) when indexing with single or double square brackets, or they can be used (with or without quotes) after a dollar sign to extract a list element.
Sometimes, you need to store multiple matrices or data frames into a single object; in this case, we can use arrays to store this data.
Data frames and matrices are of two dimensions only, but an array can be of any number of dimensions.
Here is a simple example to store three matrices of order 2 x 2 in a single array object:
Examples:
(mat.array <- array(dim=c(2,2,3))), , 1
[,1] [,2]
[1,] NA NA
[2,] NA NA
, , 2
[,1] [,2]
[1,] NA NA
[2,] NA NA
, , 3
[,1] [,2]
[1,] NA NA
[2,] NA NA
(mat.array[,,1] <- rnorm(4))[1] -0.3704286 -0.1597000 1.2355196 1.6677764
(mat.array[,,1] <- rnorm(4))[1] -0.6623115 -0.6104567 -1.1273824 0.8379214
(mat.array[,,2] <- rnorm(4))[1] -1.64012470 -0.46502691 0.97060699 -0.07112538
(mat.array[,,3] <- rnorm(4))[1] -0.8226163 -0.7321720 0.5282601 1.2565976