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"
).
<- 3.7
a 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.
<- 4L
a 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.
<- 3 > 4
a a
## [1] FALSE
class(a)
## [1] "logical"
typeof(a)
## [1] "logical"
Se pueden convertir a 1 y 0 (respectivamente) con as.numeric()
.
<- as.numeric(a)
b b
## [1] 0
Character
Texto entre comas simple o dobles.
<- "hola" # o con comas simples: 'hola'
a 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"
.
<- Sys.time()
a 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.
<- as.Date(a)
b 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.
<- c(2,4,6)
a 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.
<- factor(c("marron", "azul", "azul", "verde"))
color_ojos 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.
<- factor(c("marron", "azul", "azul", "verde"),
color_ojos 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).
<- matrix(1:6, ncol = 2)
a 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.
<- matrix(1:6, ncol = 2, byrow = TRUE)
a 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()
.
<- array(11:18, dim=c(2,2,2))
a 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.
<- list(11:13, "R", matrix(1:4,2,2))
a 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.
<- data.frame(V1=c(1,2,3), V2=c("R","S","T"), V3=c(TRUE, FALSE,TRUE))
a 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)
<- as.data.frame(paises %>% filter(anio==2007))
paises07
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.
c(4,6),4] paises07[
## [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.
<- c(5,2,4,7,9)
a c(2,2,1,5)] a[
## [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
matrix
con$nombre
o 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.
<- paises07[paises07$continente=="Asia" & paises07$esperanza_de_vida >= 80 ,] consulta
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.
<- 1:6
a 1] <- 10
a[ a
## [1] 10 2 3 4 5 6
También puedes modificar varios elementos a la vez asignando un vector de la misma longitud.
c(3,5)] <- c(300,500)
a[ a
## [1] 10 2 300 4 500 6
4:6] <- a[4:6] + 1
a[ a
## [1] 10 2 300 5 501 7
Puedes añadir elementos nuevos a un vector.
7] <- 7
a[ a
## [1] 10 2 300 5 501 7 7
También puedes modificar varios elementos asignando un único valor.
c(3,5,7)] <- 0
a[ 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)
$id <- 1:nrow(paises07) 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
.
$identificador <- NULL
paises07colnames(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.
<- 3 + c(NA, 4)
a 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
<- paises07
paises07NA $pib_per_capita[c(34,70,108)] <- NA paises07NA
kable(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.
<- c(NA, FALSE, NA, TRUE, FALSE, TRUE, NA )
a which(a)
## [1] 4 6
Utiliza which para “protegerte” de la presencia de valores faltantes en la definición de filtros.