nom <- 100
nom
## [1] 100
6 Objetos
6.1 Introducción
Un objeto es un conjunto de datos que se encuentra almacenado en R con un nombre determinado. Para almacenar cualquier objeto en R siempre utilizaremos el símbolo <-
. A la izquierda del símbolo pondremos el nombre
del objeto y a la derecha los datos que queremos almacenar. Por ejemplo, con el siguiente código decidimos almacenar el número 100
en un objeto llamado name
y a continuación lo reproducimos en la consola:
Hay algunas cosas que debemos saber en la creación de objetos:
- Podemos dar el nombre que queramos a un objeto. Las únicas limitaciones es que no puede empezar con una cifra ni tampoco puede contener espacios1 ni ninguno de los siguientes símbolos: ^, !, $, @, +, -, /, *.
1 Si queremos poner espacios lo tendremos que acotar con estos símbolos `
`
. Por ejemplo, Color de pelo
.
<- 34 #dará error
1object ! <- 44 # dará error
objec<- 54 # dará error
object first <- 64 #correcto
object_first `object first` <- 74 #correcto
- Si nombramos un objeto con el nombre de otro objeto creado previamente, R nos sobrescribirá el objeto sin avisarnos previamente.
name <- 100
name <- 50
name
## [1] 50
- R es sensible a las minúsculas y mayúsculas, de modo que guardará
Casa
ycasa
como dos objetos diferentes2.
2 Recomendamos utilizar minúsculas siempre que se pueda y utilizar el guion bajo en caso de querer separar palabras para nombrar un mismo objeto.
Num <- 1001
num <- 101
Num
## [1] 1001
num
## [1] 101
- Cuando guardemos un objeto, no aparecerá nada en la consola. Sabremos que el objeto se ha creado si observamos el Global Environment o lo consultamos con las funciones
ls()
oobjects()
. Si queremos ver reproducido el objeto en la consola al tiempo que lo creamos, deberemos acotar todo el código entre paréntesis:
(bye <- 1)
## [1] 1
Principalmente, trabajaremos con tres tipos de datos en R: valores, vectores y marcos de datos3:
3 Hay otras clases de objetos que también sirven para almacenar datos pero que no estudiaremos, como las matrices de datos (matrix) o los arrays.
6.2 Valores
Los valores son la unidad más pequeña que puede adoptar un objeto de R. Principalmente encontramos tres clases de valores: - Números - Caracteres - Lógicos
6.2.1 Números
No hace falta definir mucho qué es un número. Cualquier número almacenado en R quedará registrado como objeto numérico.
d <- 4
d
## [1] 4
En R también podemos almacenar por objeto el resultado de una operación. Lo único que nos conserva es el resultado numérico de la operación, tal como vemos si imprimimos t
.
t <- (4 + 6 + 7) / 3
t
## [1] 5.666667
Podemos realizar operaciones combinando valores numéricos y objetos que contienen valores numéricos. En el siguiente código sumamos el objeto d
, el objeto t
(que hemos creado previamente) y el número 1
:
d + t + 1
## [1] 10.66667
Fijémonos en que los objetos d
y t
han quedado guardados en el Global Environment. También podemos consultar en cualquier momento los objetos que hemos creado con la función ls()
.
6.2.2 Caracteres
En R podemos guardar cualquier texto que contenga caracteres, números y otros símbolos. Siempre deberemos poner el texto entre comillas (" "
).
z <- "Obama"
Al almacenar caracteres es muy importante saber que R es sensible a las mayúsculas. Si queremos crear un marco de datos sobre los presidentes de Estados Unidos, debemos saber que Obama
no es lo mismo que OBama
ni tampoco que OBAMA
. Hagamos la prueba:
Es un error común copiar texto de R a programas como Word que, según estén configurados, pueden cambiar automáticamente algunos símbolos del texto. El caso más habitual es el de las comillas, que las redondea. Fíjate en la diferencia:
-
"Cara"
: R entenderá que es un valor en forma de carácter y lo reproducirá sin problema. -
“Cara”
: R nos dará error porque las comillas son redondeadas.
"Obama" == "OBama"
## [1] FALSE
"OBAMA" == "OBAMA"
## [1] TRUE
En el primer caso le preguntamos si Obama
y OBama
eran el mismo valor y nos ha respondido que no, creándonos como resultado el valor lógico FALSE
. En el segundo caso nos ha confirmado que OBAMA
y OBAMA
son efectivamente el mismo valor. Esta operación que acabamos de realizar es muy importante como punto de partida para comprender la utilidad de los valores lógicos, que veremos a continuación.
6.2.3 Lógicos
Por lógica, decía Aristóteles, las ideas solo pueden ser verdaderas o falsas. No hay medias verdades. De la misma forma, los valores lógicos solo pueden ser verdad o falso. Los podemos almacenar introduciendo TRUE
(o el símbolo T
) o FALSE
(o el símbolo F
).
blonde <- T
blonde
## [1] TRUE
thin <- F
thin
## [1] FALSE
Muchos de vosotros relacionaréis los valores lógicos con las clases de filosofía del instituto. Y, efectivamente, los utilizaremos por igual. Pero también es importante saber que los operadores lógicos forman parte de nuestro día a día. Los utilizamos constantemente cuando realizamos búsquedas en Google o Instagram. Lo veremos más adelante, en el apartado de vectores lógicos. Por ahora solo necesitamos saber que existen. Y que su lógica es algo complicada, pero que nos serán de gran utilidad para trabajar con R.
6.3 Vectores
Una cadena de valores forma un vector. Cada vector solo puede almacenar valores de una misma clase. Por tanto, a los vectores que almacenan números les llamaremos vectores numéricos, a los que guardan caracteres les llamaremos vectores de carácter y a los que almacenan valores lógicos les llamaremos vectores lógicos. A partir de este tipo de vectores, también podemos crear otros. En este módulo, en total, estudiaremos seis: vectores numéricos, enteros, de carácter, factores, lógicos y de fecha.
Cuando creamos un vector, siempre concatenaremos los valores, separados por comas, dentro de la función c()
, como vemos en el siguiente ejemplo.
Es muy importante tener en cuenta la estructura básica de un vector. Si nos olvidamos de una coma entre valores o de cerrar el paréntesis, R nos dará error al ejecutar la operación.
nombre_objeto<- c(valor1, valor2, valor3, valor4)
Siempre será preferible que los nombres de los objetos tengan algo que ver con su contenido. Por ejemplo, si creamos un vector con nombres de países, nos será más útil llamarlo countries
que simplemente vector
o names
, que no nos aporta ninguna información sustantiva sobre su contenido.
En los siguientes subapartados crearemos vectores de longitud cinco, lo que significa que están formados por cinco valores. Pero debemos saber que podemos crear vectores de un solo valor hasta vectores de una longitud igual a millones de valores.
6.3.1 Vectores numéricos
El vector numérico (al que también podemos llamar doble) almacena números. Para crear uno, solo debemos separar el valor de cada número por una coma. En el siguiente código hemos creado un objeto de nombre numérico
de longitud cinco. Si queremos que los números tengan decimales, deberemos marcar los decimales con un punto como en el código num_dec
.
También podemos incluir en un vector objetos que hayamos creado anteriormente y que contengan números. En el siguiente ejemplo, para crear el objeto num_mix
utilizamos los objetos e
y d
que habíamos creado anteriormente.
e <- 3
num_mix <- c(1, 3, e, 4, d)
num_mix
## [1] 1 3 3 4 4
Una opción rápida para crear vectores numéricos que contengan secuencias correlativas de valores es utilizar el símbolo :
. En este ejemplo, el primer valor del vector adoptará el valor del objeto e
y el resto serán los números correlativos entre 4 y 7. Por tanto, será como si introdujéramos c(3, 4, 5, 6, 7) )
, pero ahorraremos código.
num_points <- c(e, 4:7)
num_points
## [1] 3 4 5 6 7
Los vectores numéricos permiten realizar operaciones matemáticas como sumar (+
), restar (-
), multiplicar (*
) o dividir (/
). Según la longitud de los vectores, podemos realizar dos tipos de operaciones:
¿Qué ocurre si, por ejemplo, realizamos una operación entre un vector con longitud 5 y un vector con longitud 2?
numeric - 1:2
## Warning in numeric - 1:2: longer object length is not a multiple of shorter
## object length
## [1] 3 3 5 5 7
Fíjate que ha completado la operación, repitiendo la secuencia de valores del vector más pequeño (1 2 1 2 1
) hasta igualarse con la longitud del vector más grande.
-
Vector con un número: Nos hace la operación de todos los valores del vector por el número en cuestión. En el siguiente caso, dividirá cada valor del vector
num_mix
entre 10.
num_mix / 10
## [1] 0.1 0.3 0.3 0.4 0.4
-
Entre vectores de igual longitud: Cuando realizamos una operación matemática entre dos o más vectores de la misma longitud, R nos realizará la operación entre los valores que tengan la misma posición en el vector. Por ejemplo, si sumamos los vectores
numeric
ynum_dec
, R sumará el primer valor denumeric
con el primer valor denum_dec
, el segundo valor denumeric
con el segundo valor denum_dec
, y así sucesivamente.
numeric
## [1] 4 5 6 7 8
num_dec
## [1] 54.98 55.97 76.58 47.33 82.24
numeric + num_dec
## [1] 58.98 60.97 82.58 54.33 90.24
Podemos realizar tantas operaciones matemáticas con tantos vectores como queramos, siempre y cuando respeten las normas descritas anteriormente. En cambio, si realizamos operaciones con vectores que tienen diferente longitud nos devolverá un aviso.
6.3.2 Vectores enteros
Una variante del vector numérico es el vector entero. Este tipo de vector, a diferencia del numérico, no puede almacenar decimales. Es un vector que no utilizaremos muy a menudo, pero que vale la pena conocer porque forma la base de otros tipos de vectores. Existen dos formas de crearlo:
A. Situando una L
en frente de cada número.
integer_L <- c(3L, 6L, 7L, 5L, 9L)
integer_L
## [1] 3 6 7 5 9
B. Utilizando la función as.integer()
.
integer_F <- as.integer(c(2022, 2021, 2021, 2021, 2020))
integer_F
## [1] 2022 2021 2021 2021 2020
6.3.3 Vectores de carácter
El vector de carácter (también llamado strings) almacena distintos valores de carácter. Por tanto, como ya hemos visto anteriormente, para crearlo deberemos acotar cada valor con las comillas (" "
) como vemos en el siguiente ejemplo.
Un error muy común es descuidarse una comilla cuando creamos un vector de carácter. Esto hará que R nos dé error al intentar reproducir la operación. Es fácil darnos cuenta del error porque los caracteres dejan de estar iluminados con distinto color:
c("C", "J", G", "C", "N")
character <- c("Colombia", "Japan", "Germany", "Chile", "New Zealand")
Los vectores de carácter no solo se restringen a los caracteres alfabéticos. También podemos almacenar números, pero al estar almacenados como caracteres no tendrán las propiedades de los números y no podremos aplicar operaciones matemáticas.
En los vectores de carácter podemos introducir todo tipo de símbolos no alfanuméricos.
mingle <- c("4$", "אַפֿגהאַניסטאַן", "الإحصاء", "%16", "統計学3")
6.3.4 Factores
Si descomponemos el factor que hemos creado con la función unclass(factor)
, podemos ver exactamente cuál es su composición real.
unclass(factor)
## [1] 1 2 3 1 4
## attr(,"levels")
## [1] "America" "Asia" "Europe" "Oceania"
En realidad, un factor es un vector entero que tiene asignada una etiqueta en cada uno de sus números. Así, el número 1 tiene asignada la etiqueta "America"
, el número 2 la etiqueta "Asia"
, y así sucesivamente.
Una variante de los vectores de carácter son los factores. De hecho, el factor es una clase de vector que, por sus características, se encuentra en medio del vector de carácter y el vector entero. Formalmente, diremos que un factor es un vector entero que puede almacenar caracteres. Esta definición cuesta entender y no nos va a servir de mucho ahora mismo, pero más adelante comprenderemos la utilidad de los factores. Por ahora, solo necesitamos saber que se crea si rodeamos el concatenado con la función factor()
.
6.3.5 Vectores lógicos
Los vectores lógicos almacenan valores lógicos y por tanto solo pueden adoptar dos valores: TRUE
o FALSE
.
logic <- c(TRUE, FALSE, FALSE, TRUE, FALSE)
Sin darnos cuenta, utilizamos a diario operadores lógicos. Cuando buscamos páginas web o fotografías en Google, los operadores lógicos se ponen a funcionar. A modo de ejemplo, hemos creado tres vectores, dos de carácter y uno numérico, con las características de cinco personajes del mundo de Hollywood.
Cuando buscamos por Johnny Depp, Google busca por todas sus bases de datos y devuelve TRUE
todas aquellas páginas que coinciden con el nombre "Johnny Depp"
.
act == "Johnny Depp"
## [1] TRUE FALSE FALSE FALSE FALSE
También podemos preguntar por los personajes nacidos a partir de 1975. En esta mini-base de datos que tenemos, R rastreará la información a born
y nos dirá qué valores son verdad (TRUE
).
born > 1975
## [1] FALSE FALSE TRUE TRUE FALSE
Con los vectores lógicos podremos realizar, más adelante, combinaciones más sofisticadas de búsqueda. La mayoría de combinaciones se harán utilizando el símbolo |
para preguntarnos si alguna de las características que pedimos está presente en la base de datos, y utilizando el símbolo &
para preguntarnos si **todas* * las características que pedimos están presentes. Veamos dos ejemplos:
Hemos preguntado por aquellos personajes de Hollywood que tienen el pelo rubio o bien (símbolo |
) que han nacido más tarde de 1975.
blond_or_1975 <- hair == "blond" | born > 1975
blond_or_1975
## [1] FALSE TRUE TRUE TRUE FALSE
En el segundo, tercero y cuarto valor, alguna de las dos condiciones es cierta.
Hemos preguntado por aquellos personajes de Hollywood que tienen el pelo rubio i (símbolo &
) han nacido más tarde de 1975.
blond_and_1975 <- hair == "blond" & born > 1975
blond_and_1975
## [1] FALSE FALSE FALSE TRUE FALSE
Solo el cuarto valor cumple todas las condiciones.
A estas alturas, quizá todavía no encontraremos mucho la utilidad en los vectores lógicos, así que no nos detendremos a explicar mucho más. Más adelante comprobaremos que son un tipo de vector esencial en la gestión de datos.
6.3.6 Vectores de fecha
Y por último, tenemos los vectores de fecha. Como hemos podido suponer, estos vectores almacenan fechas. La forma más sencilla de crearlos es introducir las fechas en un vector de carácter, de forma que en cada valor figure primero el año, después el mes y finalmente el día (YYYY/MM/DD). La función as.Date()
nos convertirá a este vector en un vector de fecha.
Si desnudamos el vector de fecha con la función unclass(date)
veremos su composición real.
unclass(factor)
## [1] 1 2 3 1 4
## attr(,"levels")
## [1] "America" "Asia" "Europe" "Oceania"
¡Sorpresa! los vectores de fecha son en realidad un vector numérico. R asigna a cada número un día, mes y año concreto. Fíjate que la fecha de 2018 corresponde con el número más bajo y el de 2021 con el número más alto. ¿Sabrías encontrar cuál es el año 0?
Tampoco nos detendremos ahora a estudiar a fondo los vectores de fecha, pero debemos saber que pueden sernos útiles para realizar operaciones entre momentos de tiempo determinados. Por ejemplo, con la siguiente operación sabemos rápidamente que hay 1015 días de diferencia entre el 15 de marzo de 2018 y el 23 de febrero de 2021.
6.3.7 Resumen vectores
Los errores más comunes de código cuando creamos vectores son:
c(4, 6 7, 8)
c(TRUE, FALSE, TRUE
c("France, "Spain", "UK")
¿Sabrías identificar los errores en cada ejemplo? Encontrarás la solución en el siguiente desplegable.
En el primer caso no hemos separado el 6 y el 7 con una coma. En el segundo caso, no hemos cerrado el paréntesis. En el tercer caso no hemos cerrado la comilla de France.
Encontrarás un buen resumen de esta sección si consultas tu Global Environment, donde has ido creando vectores de diferentes clases. Aquí puedes ver una selección. Como puedes comprobar, Global Environment muestra el nombre del objeto, seguido de la clase, la longitud y una muestra de sus primeros valores.
La clase o tipo de cada objeto se pueden consultar con las funciones class()
o typeof()
. En la tabla 6.1 tenemos un resumen de los vectores que hemos visto y sus características. Existen pequeñas diferencias entre clase y tipos de objeto, pero por ahora no son muy relevantes. Solo las exploraremos más adelante cuando sea necesario.
Clase | Tipo | Ejemplo |
---|---|---|
Carácter | Carácter | c("b", "c", "d") |
Factor | Entero | factor(c("b", "c", "d")) |
Entero | Entero | c(10L, 6L, 12L) |
Numérico | Doble | c(1.1, 3.5, 10.2) |
Fecha | Doble | as.Date(c("2019/06/04", "2019/11/02", "2020/01/23")) |
Lógico | Lógico | c(FALSE, TRUE, FALSE) |
6.4 Marco de datos
Un conjunto de vectores de igual longitud forma un marco de datos. Para crearlo, basta con introducir, separados por comas, varios vectores como argumentos sucesivos de la función tibble()
4 del paquete dplyr
.
4 Para crear marcos de datos también existe la función data.frame()
pero es algo anticuada y no la estudiaremos.
tibble(vector1, vector2, vector3, vector4...)
Para crear un marco de datos, es indispensable que todos los vectores tengan igual longitud. Si no tienen la misma longitud, nos dará error.
country <- c("Colombia", "Japan", "Germany", "Chile", "New Zealand")
year <- as.integer(c(2022, 2021, 2021, 2021, 2020))
date <- as.Date(c("2022/05/29", "2021/10/31", "2021/09/26", "2021/11/21", "2020/10/17"))
turnout <- c(54.98, 55.97, 76.58, 47.33, 82.24)
continent <- factor(c("America", "Asia", "Europe", "America", "Oceania"))
presidential <- c(TRUE, FALSE, FALSE, TRUE, FALSE)
elections <- tibble(country, year, date, turnout, continent, presidential)
Si imprimimos el marco de datos elections
, la consola nos devolverá el resultado que observamos a continuación.
elections
## # A tibble: 5 × 6
## country year date turnout continent presidential
## <chr> <int> <date> <dbl> <fct> <lgl>
## 1 Colombia 2022 2022-05-29 55.0 America TRUE
## 2 Japan 2021 2021-10-31 56.0 Asia FALSE
## 3 Germany 2021 2021-09-26 76.6 Europe FALSE
## 4 Chile 2021 2021-11-21 47.3 America TRUE
## 5 New Zealand 2020 2020-10-17 82.2 Oceania FALSE
Como podemos observar, un marco de datos es un tipo de objeto que guarda los datos en dos dimensiones: las filas y las columnas.
- Las filas serán tan largas como la longitud de cada uno de los vectores.
- Las columnas serán tan anchas como el número de vectores que conforman el marco de datos.
No nos será nada difícil contar que el marco de datos elections
está formado por cinco filas y seis columnas. Este cálculo es relativamente fácil de realizar en marcos de datos pequeños, pero la cosa se complica en marcos de datos de dimensiones descomunales. Por suerte, las dimensiones aparecen impresas al principio del marco de datos (veamos: A tibble: 5 x 6
) anterior y también tenemos otras funciones, como dim()
que nos las calculan.
Existe una segunda forma de crear marcos de datos, que es poniendo los vectores directamente dentro de la función tibble()
. En este caso, dentro de cada argumento deberemos situar el nombre que queremos que tenga el vector, seguido del símbolo igual =
y el vector correspondiente. La estructura es la siguiente:
tibble(nom_vector1 = c(valor1, valor2, valor3, etc.),
nombre_vector2 = c(valor1, valor2, valor3, etc.),
nombre_vector2 = c(valor1, valor2, valor3, etc.))
Siguiendo esta estructura, podemos crear exactamente el mismo marco de datos que hemos creado anteriormente en el objeto elections
. Este procedimiento nos evita tener que crear un objeto para cada vector, por lo que mantenemos el Global Environment más limpio.
elections <- tibble(country = c("Colombia", "Japan", "Germany", "Chile", "New Zealand"),
year = as.integer(c(2022, 2021, 2021, 2021, 2020)),
date = as.Date(c("2022/05/29", "2021/10/31", "2021/09/26", "2021/11/21", "2020/10/17")),
turnout = c(54.98, 55.97, 76.58, 47.33, 82.24),
continent = factor(c("Europe", "Asia", "Europe", "America", "Oceania")),
presidential = c(TRUE, FALSE, FALSE, TRUE, FALSE))
Cuando queramos utilizar el vector de un marco de datos, utilizaremos el símbolo $
. Así, tomando como referencia el marco de datos elections
, si queremos consultar el vector country
utilizaremos el siguiente código:
elections$country
## [1] "Colombia" "Japan" "Germany" "Chile" "New Zealand"
Recuerda que para guardar un objeto debemos utilizar el símbolo <-
y que con los vectores numéricos solo podemos realizar operaciones con otros vectores de la misma longitud o con otro valor numérico. Siguiendo esta lógica, podremos poner las cifras del vector turnout
en tanto por uno si dividimos el vector por el valor 100
y lo guardamos en el vector con el mismo nombre. Con esta acción sobreescribiremos el contenido anterior del vector.
elections$turnout <- elections$turnout / 100
elections$turnout
## [1] 0.5498 0.5597 0.7658 0.4733 0.8224
Si imprimimos de nuevo elections
veremos el resultado de la modificación.
Anteriormente, hemos visto que un vector solo puede almacenar valores de un solo tipo. ¿Has probado qué ocurre cuando intentamos crear un vector con valores de distinto tipo? Sorprendentemente, R no da error sino que nos crea el vector. Lo que ocurre es algo que se llama coerción de los datos, que significa la conversión automática de los valores de un tipo a los valores de otro tipo. Veamos algunos ejemplos:
- Combinamos un valor numérico y un valor lógico.
- Combinamos un valor de carácter y un valor lógico.
- Combinamos un valor numérico y un valor de carácter.
- Combinamos un valor numérico, un valor de carácter y un valor lógico.
Si te has fijado, la lógica que sigue es la siguiente: Carácter > Numérico > Lógico. Entre caracteres y números, R creará un vector de carácter. Entre números y valores lógicos, R creará un vector numérico. Esto es así porque es la forma que nos permite conservar el máximo de información. TRUE
y FALSE
los podemos guardar como 1
y 0
en un vector numérico, por lo que no perdemos la pista sobre qué era originariamente cada valor. En cambio, no tenemos forma de guardar los números 100
y 59
en un vector lógico sin perder información. Por último, dado que en un vector de carácter podemos guardar cualquier cosa, un valor de carácter siempre ganará la coerción contra cualquier otro valor.