Capítol 3 Objetos de R
3.1 Colecciones de objetos
3.1.1 Tipo básicos
Numeric
Los números, en R, en general se guardan en coma flotante y doble precisión ("double").
a <- 3.7
class(a)## [1] "numeric"
typeof(a)## [1] "double"
Todo objeto tiene una clase que se puede consultar con la función
class(). Adicionalmente se puede saber el tipo de datos interno contypeof().
La precisión doble es exacta hasta los 16 dígitos. La siguiente expresión debería dar 0, pero no es así.
sqrt(2)^2 - 2## [1] 4.440892e-16
Integer
Para indicar que es un entero, hay que finalizar el número con L mayúscula. Ahorran memoria pero pierden precisión. No es muy habitual su uso en Data Science.
a <- 4L
class(a)## [1] "integer"
typeof(a)## [1] "integer"
Logical
Los tipos lógicos TRUE (o T) y FALSE (o F), son de uso común para filtrar vectores.
a <- 3 > 4
a## [1] FALSE
class(a)## [1] "logical"
typeof(a)## [1] "logical"
Se pueden convertir a 1 y 0 (respectivamente) con as.numeric().
b <- as.numeric(a)
b## [1] 0
Character
Texto entre comas simple o dobles.
a <- "hola" # o con comas simples: 'hola'
class(a)## [1] "character"
typeof(a)## [1] "character"
Factor
Información categórica, por ejemplo, el color de los ojos. Por su naturaleza de conjunto, se explican dentro de la sección de vectores.
Fechas y horarios
Las fechas y horarios, son una clase compleja. Internamente son de tipo "double" con dos clases: "POSIXct" "POSIXt".
a <- Sys.time()
a## [1] "2021-01-13 01:24:34 CET"
class(a)## [1] "POSIXct" "POSIXt"
typeof(a)## [1] "double"
La clase "POSIXct" internamente almacena el número de segundos transcurridos entre la fecha y las 12:00 AM del 1 de enero de 1970 (en la zona del Tiempo Universal Coordinado (UTC)). Se puede obtener este valor con unclass().
unclass(a) # muestra el valor interno de a## [1] 1610497474
La clase Date, almacena sólo la fecha.
b <- as.Date(a)
b## [1] "2021-01-13"
class(a)## [1] "POSIXct" "POSIXt"
typeof(a)## [1] "double"
La clase Date contiene el número de días transcurridos des de 1 de enero de 1970.
unclass(b)## [1] 18640
Se ampliará esta clase en el capítulo dedicado al package lubridate.
3.1.2 Vectores
Se define mediante la función c(). Adopta el mismo tipo básico que los datos que lo componen.
class(c(3.1,9.7))## [1] "numeric"
class(c(4L, 8L))## [1] "integer"
class(c(TRUE, FALSE))## [1] "logical"
class(c("es", "un", "vector"))## [1] "character"
class(c(Sys.Date(), Sys.Date() + 1, Sys.Date()+2))## [1] "Date"
Longitud
Con length() se obtiene el número de elementos.
a <- c(2,4,6)
length(a)## [1] 3
Nombres
Los vectores pueden tener atributos. Es de uso común el atributo names.
names(a) <- c("dos","cuatro", "seis")
a## dos cuatro seis
## 2 4 6
Operaciones aritméticas
Operaciones aritméticas con vectores.
c(1,2,3) * 2 # multiplicación por escalar## [1] 2 4 6
c(1,2,3) + c(4,5,6) # suma vectores## [1] 5 7 9
c(1,2,3) * c(4,5,6) # producto elemento a elemento## [1] 4 10 18
Operaciones con texto
paste(1:3,c("uno","dos", "tres"), sep="-") # junta vectores## [1] "1-uno" "2-dos" "3-tres"
paste(c("Hola,","Mundo!"), collapse = " ") # junta elementos de un vector## [1] "Hola, Mundo!"
substr("abcdefgh", 3, 4) # subcadenas## [1] "cd"
Secuencias
3:5## [1] 3 4 5
seq(from = 2, to = 6, by = 2)## [1] 2 4 6
rep(0, times = 3)## [1] 0 0 0
rep(1:3, each = 2)## [1] 1 1 2 2 3 3
Factor
Son vectores de enteros, donde cada entero tiene asignado una etiqueta.
color_ojos <- factor(c("marron", "azul", "azul", "verde"))
color_ojos## [1] marron azul azul verde
## Levels: azul marron verde
El atributo levels contiene las etiquetas. Se puede consultar con levels(). Por defecto, los levels se crean en orden alfanumérico a partir de los valores del vector. También se pueden definir por parámetro.
color_ojos <- factor(c("marron", "azul", "azul", "verde"),
levels = c("marron", "azul", "verde"))
levels(color_ojos)## [1] "marron" "azul" "verde"
Los factores, se codifican internamente como ‘integer.’ Cada entero, contiene la posición en el vector de levels. Esta forma de codificar, ahorra memoria y acelera los cálculos. Se puede recuperar los valores integer con unclass().
class(color_ojos)## [1] "factor"
typeof(color_ojos)## [1] "integer"
unclass(color_ojos)## [1] 1 2 2 3
## attr(,"levels")
## [1] "marron" "azul" "verde"
También se pueden transformar a character con as.character().
as.character(color_ojos)## [1] "marron" "azul" "azul" "verde"
3.1.3 Matrices
Las matrices añaden otra dimensión (fila) a los vectores (columna).
a <- matrix(1:6, ncol = 2)
a## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
Por defecto se rellenan por columna, pero se puede modificar a rellenado por filas.
a <- matrix(1:6, ncol = 2, byrow = TRUE)
a## [,1] [,2]
## [1,] 1 2
## [2,] 3 4
## [3,] 5 6
Dimensión
Se puede consultar el número de filas y columnas con dim(), ncol() y nrow().
dim(a)## [1] 3 2
nrow(a)## [1] 3
ncol(a)## [1] 2
Nombres
Se puede asignar nombres a las filas y a las columnas.
colnames(a) <- paste0("V",1:ncol(a))
rownames(a) <- LETTERS[1:(nrow(a))]
a## V1 V2
## A 1 2
## B 3 4
## C 5 6
3.1.3.1 Arrays
Se puede generalizar las matrices a más de 2 dimensiones con array().
a <- array(11:18, dim=c(2,2,2))
a## , , 1
##
## [,1] [,2]
## [1,] 11 13
## [2,] 12 14
##
## , , 2
##
## [,1] [,2]
## [1,] 15 17
## [2,] 16 18
3.1.4 Listas
Las listas permiten agrupar objetos R con distintos tipos de datos.
a <- list(11:13, "R", matrix(1:4,2,2))
a## [[1]]
## [1] 11 12 13
##
## [[2]]
## [1] "R"
##
## [[3]]
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
Nombres
Se les puede asignar un nombre a cada elemento.
names(a) <- c("es_num", "es_char", "es_matriz")3.1.5 Data frames
Formalmente son una lista de vectores de la misma longitud. Tienen forma de matriz.
a <- data.frame(V1=c(1,2,3), V2=c("R","S","T"), V3=c(TRUE, FALSE,TRUE))
class(a)## [1] "data.frame"
typeof(a)## [1] "list"
kable(a)| V1 | V2 | V3 |
|---|---|---|
| 1 | R | TRUE |
| 2 | S | FALSE |
| 3 | T | TRUE |
Para conocer la estructura del objeto es útil la función str().
str(a)## 'data.frame': 3 obs. of 3 variables:
## $ V1: num 1 2 3
## $ V2: chr "R" "S" "T"
## $ V3: logi TRUE FALSE TRUE
Se utilizan las mismas reglas que en las matrices para saber la dimensión, nombres de filas y columnas.
3.2 Filtrado de objetos
Para filtrar matrices y data frames se utiliza corchetes separados por coma [,]. En el caso de vectores, corchetes simples [].
Los datos de paises07 servirán de ejemplo.
suppressPackageStartupMessages(library(tidyverse))
library(datos)
library(knitr)
paises07 <- as.data.frame(paises %>% filter(anio==2007))
class(paises07)## [1] "data.frame"
dim(paises07)## [1] 142 6
colnames(paises07)## [1] "pais" "continente" "anio" "esperanza_de_vida"
## [5] "poblacion" "pib_per_capita"
Con head() (respec. tail()), se obtiene las primeras (resp. últimas) 6 filas.
kable(head(paises07))| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita |
|---|---|---|---|---|---|
| Afganistán | Asia | 2007 | 43.828 | 31889923 | 974.5803 |
| Albania | Europa | 2007 | 76.423 | 3600523 | 5937.0295 |
| Argelia | África | 2007 | 72.301 | 33333216 | 6223.3675 |
| Angola | África | 2007 | 42.731 | 12420476 | 4797.2313 |
| Argentina | Américas | 2007 | 75.320 | 40301927 | 12779.3796 |
| Australia | Oceanía | 2007 | 81.235 | 20434176 | 34435.3674 |
Enteros positivos
Se puede indicar las posiciones fila y columna a seleccionar. Por ejemplo, la esperanza de vida de Angola y Australia.
paises07[c(4,6),4]## [1] 42.731 81.235
Para evitar que el resultado pase de data frame a vector, se utiliza el parámetro drop.
kable(paises07[c(4,6), 4, drop=FALSE])| esperanza_de_vida | |
|---|---|
| 4 | 42.731 |
| 6 | 81.235 |
Si no se informa la columna (alternativamente fila), se seleccionan todos sus valores.
kable(paises07[c(4,6),])| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 4 | Angola | África | 2007 | 42.731 | 12420476 | 4797.231 |
| 6 | Australia | Oceanía | 2007 | 81.235 | 20434176 | 34435.367 |
En el caso de vectores, se utiliza un solo corchete.
a <- c(5,2,4,7,9)
a[c(2,2,1,5)]## [1] 2 2 5 9
Observa que se pueden repetir posiciones o índices. Tampoco es necesario mantener un orden monótono en los índices.
Enteros negativos
Selecciona todas las columnas (alternativamente las filas) excepto las posiciones indicadas con valor negativo.
kable(head(paises07[,-c(3,5)]))| pais | continente | esperanza_de_vida | pib_per_capita |
|---|---|---|---|
| Afganistán | Asia | 43.828 | 974.5803 |
| Albania | Europa | 76.423 | 5937.0295 |
| Argelia | África | 72.301 | 6223.3675 |
| Angola | África | 42.731 | 4797.2313 |
| Argentina | Américas | 75.320 | 12779.3796 |
| Australia | Oceanía | 81.235 | 34435.3674 |
Nombres
Se utiliza habitualmente para seleccionar las columnas por su nombre.
kable(head(paises07[, c("pais","esperanza_de_vida")]))| pais | esperanza_de_vida |
|---|---|
| Afganistán | 43.828 |
| Albania | 76.423 |
| Argelia | 72.301 |
| Angola | 42.731 |
| Argentina | 75.320 |
| Australia | 81.235 |
Dolares y dobles corchetes
En listas y data frames se puede obtener un elemento con $nombre , o bien, con corchetes dobles
head(paises07$pib_per_capita)## [1] 974.5803 5937.0295 6223.3675 4797.2313 12779.3796 34435.3674
head(paises07[["esperanza_de_vida"]])## [1] 43.828 76.423 72.301 42.731 75.320 81.235
Una fuente habitual de error es intentar seleccionar las columnas de un objeto
matrixcon$nombreo dobles corchetes. Esto produce un error.
Valores lógicos
Se seleccionan las posiciones con valores TRUE o T y se descartan las posiciones FALSE o F.
kable(head(paises07[,c(F, F, F, T, F, T)]))| esperanza_de_vida | pib_per_capita |
|---|---|
| 43.828 | 974.5803 |
| 76.423 | 5937.0295 |
| 72.301 | 6223.3675 |
| 42.731 | 4797.2313 |
| 75.320 | 12779.3796 |
| 81.235 | 34435.3674 |
La forma habitual de seleccionar elementos de una matriz es mediante expresiones lógicas.
kable(paises07[paises07$continente=="Oceanía",])| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 6 | Australia | Oceanía | 2007 | 81.235 | 20434176 | 34435.37 |
| 92 | Nueva Zelanda | Oceanía | 2007 | 80.204 | 4115771 | 25185.01 |
Para construir estas expresiones, puedes utilizar los siguientes operadores.
| Operador | Ejemplo |
|---|---|
| a > b | ¿a mayor que b? |
| a >= b | ¿a mayor o igual que b? |
| a < b | ¿a menor que b? |
| a <= b | ¿a menor o igual que b? |
| a == b | ¿a igual a b? |
| a != b | ¿a distinto b? |
| a %in% c(b,c,d) | ¿a esta en el vector b, c o d? |
Operadores lógicos: (fuente: elaboración propia)
Estos operadores resultan extremadamente útiles en vectores.
1 > c(0, 1, 2)## [1] TRUE FALSE FALSE
c(1, 2, 3) != c(3, 2, 1)## [1] TRUE FALSE TRUE
El operador %in% tiene un funcionamiento un poco distinto. Evalúa cada elemento del objeto situado a su izquierda respecto a todos los elementos del objeto situado a su derecha.
c(1, 2, 3, 4) %in% c(3, 4, 5)## [1] FALSE FALSE TRUE TRUE
En operadores booleanos utiliza
==en vez del operador ‘=.’ Este último, hace la misma operación que<-de asignación de valores a objetos.
Operaciones booleanas
Puedes construir expresiones lógicas complejas utilizando los operadores booleanos habituales:
| Operador | Significado |
|---|---|
| cond1 & cond2 | ¿Son las dos condiciones ciertas? |
| cond1 | cond1 | ¿Es cierta alguna de las dos condiciones? |
| cond1 xor cond1 | ¿Es cierta sólo una de las condiciones? |
| !cond1 | ¿Es falsa la condición? |
| any(cond1,cond2,…) | ¿Es cierta alguna de las condiciones? |
| all(cond1,cond2,…) | ¿Son ciertas todas las condiciones? |
Operaciones booleanas (fuente: elaboración propia).
Para seleccionar los países asiáticos con esperanza de vida media en 2007 superior o igual a 80 años.
consulta <- paises07[paises07$continente=="Asia" & paises07$esperanza_de_vida >= 80 ,]kable(consulta)| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 56 | Hong Kong, China | Asia | 2007 | 82.208 | 6980412 | 39724.98 |
| 64 | Israel | Asia | 2007 | 80.745 | 6426679 | 25523.28 |
| 67 | Japón | Asia | 2007 | 82.603 | 127467972 | 31656.07 |
3.3 Modificacion objetos
R ofrece algunas facilidades para modificar los valores de sus objetos.
Filtro y asignación “]<-”
Para modificar uno elemento de un vector, R te ofrece la posibilidad de aplicar un filtro con corchetes seguido de una asignación.
a <- 1:6
a[1] <- 10
a## [1] 10 2 3 4 5 6
También puedes modificar varios elementos a la vez asignando un vector de la misma longitud.
a[c(3,5)] <- c(300,500)
a## [1] 10 2 300 4 500 6
a[4:6] <- a[4:6] + 1
a## [1] 10 2 300 5 501 7
Puedes añadir elementos nuevos a un vector.
a[7] <- 7
a## [1] 10 2 300 5 501 7 7
También puedes modificar varios elementos asignando un único valor.
a[c(3,5,7)] <- 0
a## [1] 10 2 0 5 0 7 0
En data frames (y listas) se pueden añadir columnas (resp. elementos).
suppressPackageStartupMessages(library(tidyverse))
library(datos)
library(knitr)
paises07$id <- 1:nrow(paises07)kable(head(paises07))| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | id |
|---|---|---|---|---|---|---|
| Afganistán | Asia | 2007 | 43.828 | 31889923 | 974.5803 | 1 |
| Albania | Europa | 2007 | 76.423 | 3600523 | 5937.0295 | 2 |
| Argelia | África | 2007 | 72.301 | 33333216 | 6223.3675 | 3 |
| Angola | África | 2007 | 42.731 | 12420476 | 4797.2313 | 4 |
| Argentina | Américas | 2007 | 75.320 | 40301927 | 12779.3796 | 5 |
| Australia | Oceanía | 2007 | 81.235 | 20434176 | 34435.3674 | 6 |
Modificar el nombre de una columna.
colnames(paises07)[colnames(paises07)=="id"] <- "identificador"
colnames(paises07)## [1] "pais" "continente" "anio" "esperanza_de_vida"
## [5] "poblacion" "pib_per_capita" "identificador"
Eliminar las columnas (resp. elmentos) con el objeto NULL.
paises07$identificador <- NULL
colnames(paises07)## [1] "pais" "continente" "anio" "esperanza_de_vida"
## [5] "poblacion" "pib_per_capita"
3.4 Información faltante
Para marcar los valores faltantes en R se utiliza la combinación NA (acrónimo de Not Available). Este valor especial tiene su propia aritmética.
a <- 3 + c(NA, 4)
a## [1] NA 7
Es decir, cuando un valor es desconocido, la mejor opción es no evaluar la suma con otros valores. Las expresiones lógicas se comportan de un modo similar.
c(8, NA) > 0## [1] TRUE NA
Seleccion filas missings
Para seleccionar las filas con valores faltantes, entre otros usos, puedes utilizar la función is.na().
# Introducimos algunos NA para el ejemplo
paises07NA <- paises07
paises07NA$pib_per_capita[c(34,70,108)] <- NAkable(summary(paises07NA))| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| Afganistán: 1 | África :52 | Min. :2007 | Min. :39.61 | Min. :1.996e+05 | Min. : 277.6 | |
| Albania : 1 | Américas:25 | 1st Qu.:2007 | 1st Qu.:57.16 | 1st Qu.:4.508e+06 | 1st Qu.: 1708.3 | |
| Argelia : 1 | Asia :33 | Median :2007 | Median :71.94 | Median :1.052e+07 | Median : 6223.4 | |
| Angola : 1 | Europa :30 | Mean :2007 | Mean :67.01 | Mean :4.402e+07 | Mean :11750.2 | |
| Argentina : 1 | Oceanía : 2 | 3rd Qu.:2007 | 3rd Qu.:76.41 | 3rd Qu.:3.121e+07 | 3rd Qu.:18008.7 | |
| Australia : 1 | NA | Max. :2007 | Max. :82.60 | Max. :1.319e+09 | Max. :49357.2 | |
| (Other) :136 | NA | NA | NA | NA | NA’s :3 |
Para seleccionar los registros con missing en una columna.
kable(paises07NA[is.na(paises07NA$pib_per_capita),])| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 34 | República Checa | Europa | 2007 | 76.486 | 10228744 | NA |
| 70 | Corea, Rep. Dem. | Asia | 2007 | 67.297 | 23301725 | NA |
| 108 | Ruanda | África | 2007 | 46.242 | 8860588 | NA |
Filtros missings
La presencia de NA en una variable dificulta la definición de condiciones lógicas. Por ejemplo, si seleccionamos países con PIB per cápita inferior a 500 dólares se obtiene el siguiente resultado incorrecto:
kable(paises07NA[paises07NA$pib_per_capita<500,])| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 18 | Burundi | África | 2007 | 49.580 | 8390505 | 430.0707 |
| 28 | República Democrática del Congo | África | 2007 | 46.462 | 64606759 | 277.5519 |
| NA | NA | NA | NA | NA | NA | NA |
| NA.1 | NA | NA | NA | NA | NA | NA |
| 75 | Liberia | África | 2007 | 45.678 | 3193942 | 414.5073 |
| NA.2 | NA | NA | NA | NA | NA | NA |
| 142 | Zimbabue | África | 2007 | 43.487 | 12311143 | 469.7093 |
Esta problemática se puede resolver mediante la función which().
kable(paises07NA[which(paises07NA$pib_per_capita<500),])| pais | continente | anio | esperanza_de_vida | poblacion | pib_per_capita | |
|---|---|---|---|---|---|---|
| 18 | Burundi | África | 2007 | 49.580 | 8390505 | 430.0707 |
| 28 | República Democrática del Congo | África | 2007 | 46.462 | 64606759 | 277.5519 |
| 75 | Liberia | África | 2007 | 45.678 | 3193942 | 414.5073 |
| 142 | Zimbabue | África | 2007 | 43.487 | 12311143 | 469.7093 |
La función which() devuelve la posición de los valores TRUE dentro de un vector.
a <- c(NA, FALSE, NA, TRUE, FALSE, TRUE, NA )
which(a)## [1] 4 6
Utiliza which para “protegerte” de la presencia de valores faltantes en la definición de filtros.