La información que manipulamos en R se estructura en forma de objetos.
Para trabajar con R resulta importante conocer los principales tipos de objetos y sus propiedades básicas. En general, cada tipo de objeto viene definido por una serie de atributos. Las funciones genéricas (como por ejemplo summary
o plot
) reconocen estos atributos y llevan a cabo distintos tipos de acciones en función del tipo de objeto. Aquí nos vamos a centrar solo en los objetos más utilizados: vectores, matrices, listas, data frames y factores.
Para encadenar dos vectores podemos usar el comando c()
. Los escalares son, a todos los efectos, vectores de longitud 1:
x <- c(2, 4, 6)
y <- c(3, 7)
c(x, y)
## [1] 2 4 6 3 7
Para generar sucesiones o vectores de valores repetidos podemos usar los siguientes comandos:
1:5
## [1] 1 2 3 4 5
seq(2, 10, 2)
## [1] 2 4 6 8 10
rep(c(1, 3), 4)
## [1] 1 3 1 3 1 3 1 3
Es muy importante para operar con vectores tener en cuenta la regla del reciclaje: si usamos vectores que no alcanzan la dimensión adecuada para ciertas operaciones, R automáticamente recicla el vector (repite los valores) hasta llegar a la dimensión requerida.
3 + c(1, 2, 3)
## [1] 4 5 6
c(1, 2) + c(7, 8, 9)
## Warning: longitud de objeto mayor no es múltiplo de la longitud de uno
## menor
## [1] 8 10 10
Por una parte, esta propiedad es peligrosa ya que podemos cometer errores sin darnos cuenta. La parte positiva es que muchas veces permite ahorrar código. En el segundo de los ejemplos anteriores vemos que si la dimensión del vector no es un divisor de la dimensión adecuada, recibimos un mensaje de aviso (pero se sigue aplicando el reciclaje y la operación se lleva a cabo).
Las expresiones NA, NaN, Inf, NULL
están reservadas para los valores especiales Not Available, Not a Number, Infinity y Null, respectivamente. Para entender cómo opera R con estos valores, observa los ejemplos siguientes:
x <- c(NA, NaN, Inf, 0, 3, NULL)
1/x
## [1] NA NaN 0.0000 Inf 0.3333
x - x
## [1] NA NaN NaN 0 0
1/x - (x - x)
## [1] NA NaN NaN Inf 0.3333
El valor Null corresponde a vacío y es ignorado. Puede ser útil sin embargo si queremos crear un objeto que luego vamos a ir completando poco a poco.
Se usan corchetes para generar subvectores formados por algunas de las coordenadas de un vector:
x <- (1:5)^2
x
## [1] 1 4 9 16 25
x[2]
## [1] 4
x[c(2, 5)]
## [1] 4 25
Pueden utilizarse valores negativos dentro del corchete para eliminar coordenadas:
x[-c(2, 5)]
## [1] 1 9 16
También se pueden usar operaciones lógicas para seleccionar las coordenadas que cumplen cierta condición. El comando which
se usa para saber los índices de las coordenadas que cumplen la condición:
x <- (1:5)^2
x
## [1] 1 4 9 16 25
x[x > 15]
## [1] 16 25
which(x > 15)
## [1] 4 5
Las matrices son también vectores pero con dos atributos adicionales: número de filas y número de columnas. Sin embargo, los vectores no son matrices con una fila o con una columna. Para crear una matriz:
matrix(1:3, nrow = 2, ncol = 3)
## [,1] [,2] [,3]
## [1,] 1 3 2
## [2,] 2 1 3
El primer argumento es un vector que incluye los elementos de la matriz y los otros dos corresponden al número de filas y columnas. Los elementos se van colocando por columnas. Observa cómo se ha aplicado la regla del reciclaje en el ejemplo anterior.
Veamos qué ocurre al sumar un vector y una matriz:
c(1, 2, 3) + matrix(1:9, 3, 3)
## [,1] [,2] [,3]
## [1,] 2 5 8
## [2,] 4 7 10
## [3,] 6 9 12
Tal vez es conveniente explicar paso a paso el resultado de la operación anterior:
En el ejemplo siguiente, la matriz es de nuevo considerada como un vector. Se seleccionan todas las entradas de la matriz mayores que seis y se devuelven en forma de vector. Los índices correspondientes se refieren también a la matriz considerada como vector.
x <- matrix(5:8, 3, 4)
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
x[x > 6]
## [1] 7 8 7 8 7 8
which(x > 6)
## [1] 3 4 7 8 11 12
Usando corchetes es posible extraer submatrices. Dentro del corchete, separadas por una coma, se indican las filas y columnas que queremos extraer (o eliminar si usamos números negativos). Si no se pone nada antes o después de la coma se extraen todas las filas o columnas, respectivamente:
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
x[1, 2]
## [1] 8
x[, 3]
## [1] 7 8 5
x[3, -1]
## [1] 6 5 8
Con los comandos cbind
y rbind
se pueden pegar varios vectores para formar una matriz. Si usamos cbind
cada vector será una columna de la matriz formada. Con rbind
será una fila:
y <- 1:3
z <- 4:6
cbind(y, z)
## y z
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
rbind(y, z)
## [,1] [,2] [,3]
## y 1 2 3
## z 4 5 6
Resulta bastante frecuente la necesidad de aplicar una función a cada una de las filas o columnas de una matriz. Para ello se usa el comando apply()
. Este comando tiene tres argumentos:
En el siguiente ejemplo se calculan las medias de cada columna de x
. Compara el resultado de apply
con el de aplicar directamente el comando sobre la matriz. ¿Qué ocurre en este útimo caso? Como mean
opera sobre vectores, al escribir mean(x)
se considera la matriz como un vector y se calcula el promedio de todas sus entradas.
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
mean(x)
## [1] 6.5
apply(x, 2, mean)
## [1] 6.000 6.333 6.667 7.000
En el ejemplo siguiente se ordenan de menor a mayor cada una de las filas de una matriz. Observa con atención la dimensión de la matriz resultante:
x
## [,1] [,2] [,3] [,4]
## [1,] 5 8 7 6
## [2,] 6 5 8 7
## [3,] 7 6 5 8
apply(x, 1, sort)
## [,1] [,2] [,3]
## [1,] 5 5 5
## [2,] 6 6 6
## [3,] 7 7 7
## [4,] 8 8 8
Si al aplicar la función sobre una columna o fila el resultado es otro vector, el resultado de apply
será una matriz. En este caso, los resultados de la aplicación a cada columna o fila son las columnas de la matriz resultante.
En este apartado se resumen los comandos necesarios para llevar a cabo la operaciones con matrices más habituales:
A %*% B
A*B
t(A)
det(A)
diag(A)
solve(A,b)
solve(A)
eigen(A)
Una lista es un vector de objetos de tipos distintos, que conviene agrupar en la misma estructura por diversas razones (por ejemplo, son un conjunto de resultados de un análisis estadístico de un conjunto de datos). Intuitivamente, es como una caja en la que se ponen objetos relacionados.
Es importante comprender sus propiedades porque muchas funciones de R devuelven los resultados en forma de lista. Para crearlas se usa el comando list
. En el siguiente ejemplo creamos una lista llamada milista
con tres elementos llamados nombre
, no.hijos
y edades.hijos
(este último es un vector de longitud 3):
milista <- list(nombre = "Pepe", no.hijos = 3, edades.hijos = c(4, 7, 9))
La estructura de una lista (los objetos que contiene la caja y de qué tipo son) se puede conocer con el comando str()
:
str(milista)
## List of 3
## $ nombre : chr "Pepe"
## $ no.hijos : num 3
## $ edades.hijos: num [1:3] 4 7 9
Para extrer un elemento de una lista se usa nombre_lista$nombre_objeto
si los elementos de la lista tienen nombre. También se puede usar un doble corchete y el número de orden del objeto dentro de la lista:
milista$nombre
## [1] "Pepe"
milista[[1]]
## [1] "Pepe"
milista$edades.hijos[2]
## [1] 7
En el último ejemplo anterior hemos extraído el último elemento (que era un vector) y, dentro de este, la segunda coordenada. Para reflexionar sobre la diferencia entre un único corchete y un doble corchete, piensa en las siguientes cuestiones:
milista[1]
y milista[[1]]
?milista[2:3]
?milista[[2:3]]
?Un data frame
es la estructura que se usa en R para los ficheros de datos correspondientes a una serie de variables medidas en cada sujeto o unidad bajo estudio. Intuitivamente podemos ver un data frame como una matriz con entradas que pueden ser de distintos tipos (números, palabras, etc.). Técnicamente son listas cuyos elementos son vectores de la misma longitud.
Para crearlos se utiliza el comando data.frame
. En el siguiente ejemplo creamos uno llamado mifichero
con dos vectores llamados edad
y grupo
. Los vectores (variables) son de la misma longitud pero son heterogéneos en el sentido de que el primero contiene números y el segundo letras.
x <- 7:9
y <- c("a", "b", "c")
mifichero <- data.frame(edad = x, grupo = y)
mifichero
## edad grupo
## 1 7 a
## 2 8 b
## 3 9 c
Dado que los data frames son un tipo particular de listas, podemos aplicarles todos los comandos que hemos introducido en la sección anterior:
str(mifichero)
## 'data.frame': 3 obs. of 2 variables:
## $ edad : int 7 8 9
## $ grupo: Factor w/ 3 levels "a","b","c": 1 2 3
mifichero$edad
## [1] 7 8 9
mifichero[[2]]
## [1] a b c
## Levels: a b c
Al mismo tiempo, también admiten algunos de los comandos que se aplican a las matrices. Para extraer todas las variables correspondientes a la segunda observación (la segunda fila del fichero) podemos escribir:
mifichero[2, ]
## edad grupo
## 2 8 b
Si queremos aplicar el mismo comando a todas las variables de un fichero podemos usar dos comandos, lapply
y sapply
, que difieren en la estructura que tiene el resultado:
lapply
para aplicar una función a cada elemento de una lista (el resultado es otra lista),sapply
actúa igual, pero el resultado es un vector o una matriz.Como ejemplo tomamos el fichero faithful
que contiene datos de duración y tiempo de espera entre erupciones del geyser Old faithful en Yellowstone. Si queremos obtener las principales medidas descriptivas de cada una de las dos variables del fichero:
sapply(faithful, summary)
## eruptions waiting
## Min. 1.60 43.0
## 1st Qu. 2.16 58.0
## Median 4.00 76.0
## Mean 3.49 70.9
## 3rd Qu. 4.45 82.0
## Max. 5.10 96.0
lapply(faithful, summary)
## $eruptions
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1.60 2.16 4.00 3.49 4.45 5.10
##
## $waiting
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 43.0 58.0 76.0 70.9 82.0 96.0
Observa que los resultados son los mismos, pero estructurados de manera diferente.
Los factores son las estructuras que se utilizan para manejar las variables cualitativas en los análisis estadísticos. Se pueden contemplar como un vector al que se añade un poco más de información consistente en los distintos valores presentes en el vector, llamados niveles. Se crean usando el comando factor()
. Veamos un ejemplo:
x <- c(2, 2, 3, 4, 2, 5)
x
## [1] 2 2 3 4 2 5
xfactor <- factor(x)
xfactor
## [1] 2 2 3 4 2 5
## Levels: 2 3 4 5
El fichero iris
contiene los famosos datos de lirios de Fisher con medidas de la longitud y anchura del sépalo y pétalo de 150 lirios correspondientes a tres especies. Veamos las primeras observaciones del fichero:
head(iris)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
La última variable es un factor que indica la especie a la que corresponde cada observación:
iris$Species
## [1] setosa setosa setosa setosa setosa setosa
## [7] setosa setosa setosa setosa setosa setosa
## [13] setosa setosa setosa setosa setosa setosa
## [19] setosa setosa setosa setosa setosa setosa
## [25] setosa setosa setosa setosa setosa setosa
## [31] setosa setosa setosa setosa setosa setosa
## [37] setosa setosa setosa setosa setosa setosa
## [43] setosa setosa setosa setosa setosa setosa
## [49] setosa setosa versicolor versicolor versicolor versicolor
## [55] versicolor versicolor versicolor versicolor versicolor versicolor
## [61] versicolor versicolor versicolor versicolor versicolor versicolor
## [67] versicolor versicolor versicolor versicolor versicolor versicolor
## [73] versicolor versicolor versicolor versicolor versicolor versicolor
## [79] versicolor versicolor versicolor versicolor versicolor versicolor
## [85] versicolor versicolor versicolor versicolor versicolor versicolor
## [91] versicolor versicolor versicolor versicolor versicolor versicolor
## [97] versicolor versicolor versicolor versicolor virginica virginica
## [103] virginica virginica virginica virginica virginica virginica
## [109] virginica virginica virginica virginica virginica virginica
## [115] virginica virginica virginica virginica virginica virginica
## [121] virginica virginica virginica virginica virginica virginica
## [127] virginica virginica virginica virginica virginica virginica
## [133] virginica virginica virginica virginica virginica virginica
## [139] virginica virginica virginica virginica virginica virginica
## [145] virginica virginica virginica virginica virginica virginica
## Levels: setosa versicolor virginica
Supongamos que queremos calcular la media de las lóngitudes de los pétalos para cada una de las tres especies. Para ello podemos usar la funcion tapply()
, que tiene tres argumentos:
tapply(iris$Petal.Length, iris$Species, mean)
## setosa versicolor virginica
## 1.462 4.260 5.552