Crear nuevo proyecto

Para que mantengas un buen orden en tu aprendizaje, es momento de crear un nuevo proyecto en el que irás anotando todo lo que aprendas en esta sesión. Cabe mencionar que todo lo que anotes deberás publicarlo al final en tu perfil de Rpubs.com

  • Crear un nuevo proyecto en nuevo directorio: “08-ejercicios”

Crear documento R Markdown

  • Crear un nuevo archivo R Markdown:
    • Documento HTML
    • Título: “Elementos básicos de R”
    • Contenido: Según las notas que tomes en la sesión

Operadores elementales

Aritméticos

Los operadores, como dice su nombre, nos permiten realizar operaciones entre ciertos valores de manera similar a como lo haríamos con una calculadora. Los siguientes nos permiten realizar operaciones aritméticas básicas:

Operador Operación
+ Adición
- Sustracción
* Multiplicación
/ División real
** o ^ Potencia
() Para priorizar operaciones al interior de los paréntesis

1994 + 27
## [1] 2021
28 / 365 * 100
## [1] 7.671233
2 ** 3
## [1] 8
(((1+2)*3)**2)/3
## [1] 27

Operador de asignación

Antes de explotar al máximo las capacidades de R, es necesario conocer otro operador fundamental: el de asignamiento. Está compuesto por el signo “menor que” (<) y el signo de resta (-), que al juntarse lucen como una flecha que apunta hacia la izquierda (<-).

Este operador sirve para asignar un nombre a cualquier objeto o valor, de tal modo podamos acceder a él con mayor facilidad. Por ejemplo, podemos asignarle el nombre “resultado” al resultado de la operación que realizamos anteriormente.

resultado <- (((1+2)*3)**2)/3

A simple vista, nada ha cambiado, pero cuando accedemos al objeto resultado ahora obtenemos inmediatamente la respuesta de nuestra operación.

resultado
## [1] 27

Si te diriges al panel Environment en RStudio, puedes ver que el objeto resultado está almacenado allí.

Es importante saber que el nombre asignado es arbitrario, es decir, no afectará el valor que está siendo asignado. Es buena práctica usar solo nombres que comiencen por letras y contengan solo letras, números y subguión. Por ejemplo: mi_valor, tabla1, mi_nueva_tabla, conjuntoDeDatos, etc.

Actualizar valor asignado

Si por algún motivo necesitamos actualizar el valor asignado a nuestro objeto, basta con volver a asignar el mismo nombre a otro valor. Incluso se puede hacer referencia al valor anterior para modificarlo. No hay un límite de veces que el valor de un objeto puede ser modificado. En el siguiente ejemplo, sumaremos 3 a resultado para obtener 30.

resultado <- resultado + 3

Nuevamente, podemos ver el cambio al inspeccionar el elemento.

resultado
## [1] 30

Vectores

Identificando los vectores

Los siguientes objetos fundamentales para el manejo de R son los vectores. Estos pueden ser de dos tipos: atómicos y listas. La diferencia entre ellos radica en el tipo de información que pueden contener. Para efectos de estos tutoriales, consideraremos las listas como vectores “especiales” junto a otros que explicaremos más adelante.

Vectores atómicos

Los cuatro principales tipos de vectores atómicos son: logical, double, integer y character.

  • logical: pueden asumir dos valores: TRUE o FALSE(o en su forma abreviada T o F).
  • integer puede asumir números enteros (1, 2, 3, -1, 1000, etc)
  • double: pueden asumir números reales (1.0, 1.1, -1.999, 3.14159, etc)
  • character: pueden asumir cualquier cadena de texto (“hola”, “buongiorno”, “$5.99”, etc)

Los de tipo double e integer también son conocidos como numéricos.

En el siguiente recuadro de código podemos ver un ejemplo de cada uno:

v_logical <- TRUE
v_double <- 3.1416
v_integer <- 5L
v_character <- "Hola mundo"

Si estamos atentos, vemos que el integer va acompañado de una “L” al final. Esto es necesario porque R interpreta por defecto cualquier número como double. Tanto los double como los integer pertenecen a la categoría de vectores numéricos. Los character siempre estarán rodeados de comillas ("").

Comprobar tipo de vector con is.*()

Para comprobar si nuestro vector es de un tipo determinado utilizamos una función de forma is.*() reemplazando el * por el tipo que queremos comprobar.

is.logical(v_logical)
## [1] TRUE
is.numeric(v_double)
## [1] TRUE
is.integer(v_double)
## [1] FALSE

Podemos ver que por cada consulta obtenemos un valor logical TRUE cuando se cumple la condición y FALSE cuando no se cumple. Es decir, es cierto que v_logical es logical, es cierto que v_double es numérico y es falso que v_double es integer. El valor logical obtenido con cada consulta es un vector en sí mismo.

Comprobar tipo de vector con typeof()

Otra manera de verificar el tipo de vector que tenemos es con la función typeof(). Esta nos devuelve un character indicando el tipo de vector que tenemos.

typeof(v_character)
## [1] "character"
typeof(v_integer)
## [1] "integer"

Ejercicio

1. Identificar tipo de vector

En bloques de código, ejecuta el código necesario para identificar el tipo de los siguientes valores:

  1. "3.1415"
  2. FALSE
  3. 1 + 10
  4. 142365L

2. Descartar tipo de vector

¿Cuáles de los siguientes vectores son de tipo double?

  • 100
  • 7.9
  • "50.0 mm"
  • 1024L

Vectores con más de un elemento

Hasta el momento hemos visto vectores que contienen un solo elemento. Sin embargo, es sumamente común encontrarse con vectores de mayor longitud. Por ejemplo, el vector letters contiene todas las letras minúsculas del alfabeto. Podemos consultar la longitud de un vector con la función length().

Esto es muy útil cuando sabemos que nuestro vector podría contener una gran cantidad de elementos y no queremos inspeccionarlos todos. El número que vemos rodeado entre corchetes ([]) en nuestro resultado nos indica el índice que el elemento siguiente tiene en el vector. Es por ello que hasta el momento en cada operación que realizábamos hemos obtenido un “[1]” antes de cada resultado.

length(v_logical)
## [1] 1
length(letters)
## [1] 26
letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"

Para formar vectores de longitud mayor a uno (1) se utiliza la función c() agregando como argumentos todos los elementos que queremos.

mi_vector_largo <- c("elemento1", 
                     "elemento2", 
                     "elemento3", 
                     "elemento4")

mi_vector_largo
## [1] "elemento1" "elemento2" "elemento3" "elemento4"

Operador de secuencia simple

Para vectores numéricos, también es posible utilizar el signo dos puntos (:) como operador para crear una secuencia, que avanza de uno en uno, desde un número a otro. El vector resultado incluirá a los dos números utilizados en la operación.

mi_vector_numerico1 <- 1:6

mi_vector_numerico1
## [1] 1 2 3 4 5 6

Concatenar vectores largos

Podemos hacer uso de c() nuevamente para seguir haciendo crecer nuestro vector. Incluso podemos usar una operación de secuencia como argumento.

mi_vector_numerico2 <- 11:16

mi_vector_muy_largo <- c(mi_vector_numerico1, 
                         mi_vector_numerico2, 
                         21:26)

mi_vector_muy_largo
##  [1]  1  2  3  4  5  6 11 12 13 14 15 16 21 22 23 24 25 26

Al consultar el tipo de vector que hemos creado, vemos que mantiene el mismo tipo que sus “ancestros”: integer.

typeof(mi_vector_muy_largo)
## [1] "integer"

Ejercicio

1. Crear secuencia

En bloques de código, ejecuta código para obtener lo siguiente:

  • Crea un secuencia que vaya del 100 al 200
  • ¿Qué tipo de vector se formó con esa secuencia?

2. Crear vector de nombres

En bloques de código, ejecuta código para obtener lo siguiente:

  • Crea un vector en el que cada elemento es una parte de tu nombre completo. Por ejemplo:
mi_nombre <- c("Barack", "Obama")
  • ¿Qué tipo de vector se formó con esta operación?

Operaciones con vectores

Es posible realizar operaciones entre vectores. Cuando los vectores tienen la misma longitud, la operación se hará elemento a elemento de acuerdo a su índice. Es decir, el primer elemento del vector 1 con el primer elemento del vector 2, el segundo elemento del vector 1 con el segundo elemento del vector 2, y así sucesivamente.

mi_secuencia1 <- 1:10
mi_secuencia2 <- 11:20

mi_secuencia1 + mi_secuencia2
##  [1] 12 14 16 18 20 22 24 26 28 30
mi_secuencia2 - mi_secuencia1
##  [1] 10 10 10 10 10 10 10 10 10 10
mi_secuencia1 * mi_secuencia2
##  [1]  11  24  39  56  75  96 119 144 171 200

Reciclaje de vectores

Cuando un vector tienen longitud de uno (1), su valor se reciclará.

mi_secuencia1 + 1
##  [1]  2  3  4  5  6  7  8  9 10 11
mi_secuencia1 * 5
##  [1]  5 10 15 20 25 30 35 40 45 50
mi_secuencia1 ** 2
##  [1]   1   4   9  16  25  36  49  64  81 100

Coerción y valores NA

Coerción de vectores

Crear vectores más largos puede tener efectos inesperados para el usuario que no está atento. Veamos el siguiente ejemplo:

vector_combinado <- c(mi_vector_muy_largo, "1")

typeof(vector_combinado)
## [1] "character"

Al agregar "1" a nuestro vector, su tipo ha cambiado a character. ¿Por qué sucede esto? En primer lugar, hay que tener claro que "1" no es lo mismo que 1. Recordemos que todo valor que está entre comillas es de tipo character, incluso si se trata de números.

En segundo lugar, tengamos en cuenta que los vectores atómicos sólo pueden tener un tipo. Esto quiere decir que cuando los tipos de los elementos que se combinan dentro del vector son diferentes, R debe decidir cuál de los tipos de vector mantener, eligiéndo sólo uno. Este procedimiento es llamado coerción.

Reglas de coerción implícita

Aunque suena complicado, las reglas de coerción son bastante sencillas. R le dará prioridad a mantener el tipo de vector según el siguiente orden:

  1. Character
  2. Double
  3. Integer
  4. Logical

Es decir, ante cualquier conflicto en el tipo de vectores a combinar se preservará el tipo que tenga más alta prioridad.

Si nos detenemos a analizar por qué sucede, es bastante evidente. Los valores logical son en realidad leídos por la computadora como 1 cuando son TRUE y como 0 cuando son FALSE. Es por ello que la siguiente operación no nos arroja un error.

1L + TRUE
## [1] 2

Del mismo modo, sabemos que cualquier número entero también puede ser expresado como número racional. Es por ello que los integer son coercionados a double cuando hay conflicto entre ellos.

typeof(1L + 3.1416)
## [1] "double"

¿Es posible convertir texto a números en R? No. Es por ello que cuando un vector tipo character se combina con cualquier otro tipo de vector, prevalece el tipo character, como en el ejemplo que vimos al inicio de esta sección.

Coerción explícita

En todos los casos de coerción que hemos mencionado hasta el momento R ha decidido mediante sus propias reglas qué tipo de vector debe prevalecer, aplicando coerción implícita. Este procedimiento puede ocasionar problemas cuando el usuario no tiene suficientemente claras las reglas de coerción.

La coerción explícita permite decidir de antemano qué tipo de vector queremos obtener. Para ello se hace uso de una función de la forma as.*() donde * representa el tipo deseado.

vector_true_integer <- as.integer(TRUE)

typeof(vector_true_integer)
## [1] "integer"

En este ejemplo, hemos usado as.integer() para cambiar el tipo de nuestro vector, de logical a integer. Es posible hacer lo mismo para otros tipos de vectores. Tomemos en cuenta que la transformación se realiza de manera directa, sin respetar el orden de prioridad.

as.character(TRUE)
## [1] "TRUE"

Es por ello que TRUE se convierte directamente en el character "TRUE" sin convertirse primero en el integer 1L, luego en el double 1 y luego en el character "1". De aquí viene el verdadero poder de la coerción explícita, porque nos permite incluso “revertir” el orden de prioridad que R usa en la coerción implícita. Es decir, podemos convertir cualquier tipo de vector a otro.

typeof(as.logical("TRUE"))
## [1] "logical"
typeof(as.integer("10"))
## [1] "integer"
typeof(as.integer(5.0))
## [1] "integer"
typeof(as.double("6.108"))
## [1] "double"

Coerción puede perder información

De todos modos, esto se debe usar con precaución. Sabemos que todo logical puede convertirse a integer, estos a su vez pueden convertirse a double y estos a character sin perder ninguna información. No sucede lo mismo en el procedimiento reverso. Por ejemplo, esto sucede cuando queremos convertir un double con cifras decimales a integer.

as.integer(5.4234)
## [1] 5

El contenido decimal se pierde, porque R no lo necesita en el integer, y no es posible recuperarlo aún retransformando el valor a double en la misma línea de código.

as.double(as.integer(5.4234))
## [1] 5

Algo similar sucede cuando intentamos convertir a logical valores numéricos diferentes a 0.

as.logical(8)
## [1] TRUE
as.logical(-0.000000135)
## [1] TRUE

R interpreta como TRUE todo número diferente a 0. Es probable que no sea el resultado que esperábamos en esta transformación.

Ejercicio

Práctica de coerción

Intenta este ejercicio primero sin ejecutar código. Luego, verifica si tus suposiciones eran correctas.

¿Qué tipos de vector obtenemos en los siguientes bloques de código?

Una vez que compruebes de qué tipo son los vectores creados, agrega una explicación de esa coerción antes de cada bloque de código.

test1 <- c(10:15, TRUE)

test2 <- c(10:15, 16)

test3 <- c(10:15, "FALSE")

test4 <- c("10:15", 16L)

Valores NA

¿Qué sucederá si intentamos convertir una palabra a número?

as.integer("sustantivo")

R no es capaz de asignar un valor numérico a "sustantivo" y como resultado nos arroja un advertencia o warning: NAs introduced by coercion. El valor NA representa un valor perdido y no es posible transformarlo. Los valores perdidos pueden aparecer en nuestros datos por diferentes motivos, desde la recolección hasta la transformación de nuestra data.

as.integer("sustantivo")
## Warning: NAs introduced by coercion
## [1] NA

Suma con valor NA

Debemos ser extremadamente cuidadosos al trabajar con ellos, porque pueden generar algunos problemas indeseados. Por ejemplo, si queremos obtener la suma de todos los elementos de un vector, usando la función sum(), y resulta que uno de ellos es un NA.

vector_con_NA <- c(1, 2, 3, 4, NA, 6, 7)
sum(vector_con_NA)
## [1] NA

El resultado obtenido es simplemente NA. El mismo problema se extiende al querer obtener un promedio usando la función mean().

mean(vector_con_NA)
## [1] NA

Argumento na.rm

Felizmente, estas funciones permiten proporcionar el argumento na.rm = TRUE para ignorar los valores NA y trabajar sólo con valores válidos.

sum(vector_con_NA, na.rm = TRUE)
## [1] 23
mean(vector_con_NA, na.rm = TRUE)
## [1] 3.833333

Sin embargo, no necesariamente encontraremos esta herramienta en todas las funciones que trabajan con vectores. Por ello es indispensable estar atentos al trabajar nuestros datos y revisar la documentación de las funciones con las que estamos trabajando.

Ejercicio

Crear vectores

  1. Crea un vector de cualquier tipo con 10 elementos
  2. Crea un vector de cualquier tipo con 10 elementos, el último elemento debe ser un NA
  3. Crea un vector de cualquier tipo con 10 elementos, el sexto elemento debe ser un NA

Comprobar tipo de vector

Intenta este ejercicio primero sin ejecutar código. Luego, verifica si tus suposiciones eran correctas.

¿Qué tipos de vector obtenemos en los siguientes bloques de código?

Una vez que compruebes de qué tipo son los vectores creados, agrega una explicación de esa coerción antes de cada bloque de código.

test1 <- c(1:6, NA)
test2 <- test1 * 10
test3 <- test1 + NA
test4 <- c(test1, "7")
test5 <- c(test1, TRUE)
test6 <- NA * NA

Operaciones lógicas

Del mismo modo en que los operadores aritméticos nos permitían obtener un resultado aritmético (aka, numérico) en nuestros cálculos, existen otros operadores que nos permiten obtener resultados lógicos.

Operadores relacionales

Los primeros de ellos son los relacionales, y ya los conocemos desde el colegio, pero es bueno saber cómo escribirlos en R. La siguiente tabla nos muestra para qué sirve cada uno de ellos.

Operador Uso
> Mayor que
< Menor que
== Igual que
!= Diferente que
>= Mayor o igual que
<= Menor o igual que

Usando operadores relacionales

Empecemos por definir una secuencia del 1 al 6 con la cual vamos a hacer nuestras comparaciones.

secuencia <- 1:6

Primero vamos a utilizar los operadores de igualdad y desigualdad. Tengamos en cuenta que al igual que con las operaciones aritméticas, al comparar una costante, esta se recicla.

secuencia
## [1] 1 2 3 4 5 6
# igual que
secuencia == 6
## [1] FALSE FALSE FALSE FALSE FALSE  TRUE
# diferente que
secuencia != 6
## [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

Obtenemos los resultados de las comparaciones. En aquellos valores que cumplan la condición, obtenemos un valor TRUE. Vemos que sucede lo mismo cuando usamos los demás operadores relacionales.

secuencia
## [1] 1 2 3 4 5 6
# mayor que
secuencia > 4
## [1] FALSE FALSE FALSE FALSE  TRUE  TRUE
# menor que
secuencia < 4
## [1]  TRUE  TRUE  TRUE FALSE FALSE FALSE

# mayor o igual que
secuencia >= 4
## [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE
# menor o igual que
secuencia <= 4
## [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE

Ten cuidado al comparar vectores character como numericos porque pueden devolver resultados inesperados. No olvides que operar con un NA siempre devolverá NA.

100 < "11"
## [1] TRUE
1000 > NA
## [1] NA

Operadores lógicos

Para potenciar nuestras habilidades de comparación, podemos hacer uso de operadores lógicos. La siguiente tabla te muestra cuáles son:

Operador Uso
& Y lógico
| O lógico
! NO lógico

Usaremos una secuencia un poco más larga para ver mejor cómo usarlos:

secuencia2 <- 1:8

secuencia2
## [1] 1 2 3 4 5 6 7 8
# Y lógico: el número debe ser mayor que tres Y menor que 6
secuencia2 > 3 & secuencia2 < 6
## [1] FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
# O lógico: el número debe ser menor que tres O mayor que 6
secuencia2 < 3 | secuencia2 > 6
## [1]  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE
# NO lógico: cambia el valor de la operación
! secuencia2 <= 6
## [1] FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE

Listas

Los cuatro vectores que conocimos en la sesión 1 son los llamados vectores atómicos, porque pueden almacenar un tipo específico de información. Hemos conocido también los factores y datetimes, que permiten alterar el comportamiento de estos vectores atómicos. Ahora nos toca conocer las listas.

Función list()

Las listas son objetos especiales, porque nos permiten almacenar cualquier tipo de información. Para crear una, usamos la función list(). Se pueden inspecionar sus elementos de la misma manera que con cualquier otro vector.

mi_vector_1 <- c(1L, "Hola mundo", 3.14159, TRUE)
mi_lista_1 <- list(1L, "Hola mundo", 3.14159, TRUE)

¿Cuál es el resultado de los siguientes bloques de código?

typeof(mi_vector_1)
## [1] "character"
typeof(mi_lista_1)
## [1] "list"

Las listas lucen diferente que un vector atómico

mi_lista_1
## [[1]]
## [1] 1
## 
## [[2]]
## [1] "Hola mundo"
## 
## [[3]]
## [1] 3.14159
## 
## [[4]]
## [1] TRUE

Vemos que este objeto aceptó los cuatro tipos de vectores atómicos sin problema, y que al ser inspeccionado, cada elemento correspondía en sí mismo a un vector atómico.

Elementos con nombre

Del mismo modo que podíamos combinar vectores atómicos con otros vectores atómicos, en las listas podemos agregar vectores creados previamente. En este caso, cada uno de ellos conserva su singularidad. Al crear la lista, podemos asignarle un nombre a cada elemento.

vec_integer <- 1:10
vec_logical <- c(TRUE, FALSE, TRUE, FALSE)
vec_double <- vec_integer*10
vec_character <- as.character(vec_double)
mi_lista_2 <- list(enteros = vec_integer,
                   logicos = vec_logical,
                   decimales = vec_double,
                   texto = vec_character)

mi_lista_2
## $enteros
##  [1]  1  2  3  4  5  6  7  8  9 10
## 
## $logicos
## [1]  TRUE FALSE  TRUE FALSE
## 
## $decimales
##  [1]  10  20  30  40  50  60  70  80  90 100
## 
## $texto
##  [1] "10"  "20"  "30"  "40"  "50"  "60"  "70"  "80"  "90"  "100"

Combinar listas

Para combinar una lista con otra, basta con incluirlas dentro de una lista nueva. En el código de abajo, se creará una lista con dos elementos, cada uno de ellos sigue siendo una lista.

mi_lista_combinada <- list(mi_lista_1, mi_lista_2)

mi_lista_combinada
## [[1]]
## [[1]][[1]]
## [1] 1
## 
## [[1]][[2]]
## [1] "Hola mundo"
## 
## [[1]][[3]]
## [1] 3.14159
## 
## [[1]][[4]]
## [1] TRUE
## 
## 
## [[2]]
## [[2]]$enteros
##  [1]  1  2  3  4  5  6  7  8  9 10
## 
## [[2]]$logicos
## [1]  TRUE FALSE  TRUE FALSE
## 
## [[2]]$decimales
##  [1]  10  20  30  40  50  60  70  80  90 100
## 
## [[2]]$texto
##  [1] "10"  "20"  "30"  "40"  "50"  "60"  "70"  "80"  "90"  "100"

Dataframes

¿Qué es un data.frame?

Un data.frame es una versión bi-dimensional de una lista, lo que ocasiona que se comporte de manera similar a una tabla. Debido a que esa estructura facilita mucho su comprensión de manera visual y almacenamiento, su uso es muy extendido en el análisis de datos.

Fuera de R, los programas más conocidos que también almacenan sus datos tabularmente son Excel, Google Sheets y SPSS. Es una de las razones por las que resulta muy sencillo trasladar el trabajo realizado en esos programas hacia R.

Es muy común referirse a un data.frame como df, en forma abreviada.

Crear un data.frame

El proceso para crearlos es muy similar al de una lista nombrada. En el siguiente código, estamos creando el objeto df, conformado por tres vectores de cinco elementos cada uno.

df <- data.frame(
  columna1 = 1:5,
  columna2 = c("uno", "dos", "tres", "cuatro", "cinco"),
  columna3 = c("one", "two", "three", "four", "five")
  )
df
##   columna1 columna2 columna3
## 1        1      uno      one
## 2        2      dos      two
## 3        3     tres    three
## 4        4   cuatro     four
## 5        5    cinco     five

En un data.frame, cada vector se convierte en una columna, con cada uno de sus elementos convirtiéndose en una fila, en el orden en que aparecen. Además de eso, el número de fila nos aparece automáticamente como una columna sin nombre.

Obtener un data.frame a partir de una lista

notas <- list(
  matematica = c(20, 15, 17, 19),
  lenguaje = c(18, 12, 11, 19),
  ciencias = c(19, 14, 15, 17)
)
notas
## $matematica
## [1] 20 15 17 19
## 
## $lenguaje
## [1] 18 12 11 19
## 
## $ciencias
## [1] 19 14 15 17

df_notas <- as.data.frame(notas)
df_notas
##   matematica lenguaje ciencias
## 1         20       18       19
## 2         15       12       14
## 3         17       11       15
## 4         19       19       17

Podemos identificar los data.frame porque poseen la clase “data.frame”,

class(df_notas)
## [1] "data.frame"

Obtener un data.frame a partir de vectores

Al igual que con una lista, puedo obtener los elementos (columnas) de mi data.frame a partir de vectores creados previamente. En este caso, la columna heredará el nombre del objeto a partir del cual es creado.

alumnos <- c("Amanda", "Brenda", "Charlie", "Dario")
sexo <- c("F", "F", "M", "M")

df_alumnos <- data.frame(alumnos, sexo)
df_alumnos
##   alumnos sexo
## 1  Amanda    F
## 2  Brenda    F
## 3 Charlie    M
## 4   Dario    M

Ejercicio

Crea tu primer data.frame

Ahora es tu turno. Crea un data.frame con las siguientes tres columnas:

  • nombre
  • apellido
  • cargo

Cada fila debe representar el nombre de alguien famoso.

Guardalo en tu Environment con el nombre “mi_primer_dataframe”

Ejemplo

##    nombre apellido         cargo
## 1 Tsunade    Senju Quinto Hokage
## 2  Minato Namikaze Cuarto Hokage
## 3 Hiruzen Sarutobi Tercer Hokage

head() y tail()

Hasta el momento, hemos trabajado con data.frames pequeños. Normalmente, nuestros datos pueden llegar a tener una gran cantidad de filas y columnas. El data.frame alfabeto contiene dos columnas, cada una contiene las 26 letras del alfabeto (inglés) en mayúsculas y minúsculas, respectivamente.

alfabeto <- data.frame(LETTERS, letters)

Al inspeccionar su contenido obtenemos:

alfabeto
##    LETTERS letters
## 1        A       a
## 2        B       b
## 3        C       c
## 4        D       d
## 5        E       e
## 6        F       f
## 7        G       g
## 8        H       h
## 9        I       i
## 10       J       j
## 11       K       k
## 12       L       l
## 13       M       m
## 14       N       n
## 15       O       o
## 16       P       p
## 17       Q       q
## 18       R       r
## 19       S       s
## 20       T       t
## 21       U       u
## 22       V       v
## 23       W       w
## 24       X       x
## 25       Y       y
## 26       Z       z

Todos los elementos del data.frame aparecen en nuestra pantalla. Con un conjunto de datos de 26 filas esto aún es manejable, pero imagina que estás trabajando con miles o millones de datos, imprimir todos los elementos en tu pantalla no sólo es molesto sino también inútil.

Felizmente, puedes hacer uso de la función head(). Por defecto, imprimirá las seis primeras filas del data.frame que le ingresemos, pero podemos especificar otro número.

# Seis primeras filas por defecto
head(alfabeto)
##   LETTERS letters
## 1       A       a
## 2       B       b
## 3       C       c
## 4       D       d
## 5       E       e
## 6       F       f

# Especificando el número de filas requerido
head(alfabeto, 8)
##   LETTERS letters
## 1       A       a
## 2       B       b
## 3       C       c
## 4       D       d
## 5       E       e
## 6       F       f
## 7       G       g
## 8       H       h

Si lo queremos es ver las últimas filas del data.frame, podemos hacer uso de la función tail(). Nuevamente, por defecto imprime las seis últimas filas, pero se le puede especificar otra cantidad.

# Seis últimas filas
tail(alfabeto)
##    LETTERS letters
## 21       U       u
## 22       V       v
## 23       W       w
## 24       X       x
## 25       Y       y
## 26       Z       z

# Especificando el número de filas requerido
tail(alfabeto, 3)
##    LETTERS letters
## 24       X       x
## 25       Y       y
## 26       Z       z

Tibbles

¿Qué son los tibbles?

Así como los data.frames son listas que se comportan de manera especial, los tibbles son data.frames que se comportan de manera especial. Vamos a conocer de qué manera lo hacen, y por qué es preferible trabajar con ellos.

Ten encuenta que para ello es necesario utilizar el paquete tibble.

library(tibble)
## Warning: package 'tibble' was built under R version 4.1.1

Los tibble son objetos ampliamente utilizados en la actualidad y son parte fundamental del tidyverse, un conjunto de paquetes que comparten una filosofía en común, con el fin de hacer el análisis de datos más accesible y reproducible.

Esta filosofía es visiblemente respaldada por los desarrolladores de RStudio. Debido a esta popularidad , es bastante probable que cuando veas que alguien está hablando de un data.frame, en realidad se esté refiriendo a un tibble.

Crear un tibble a partir de un data.frame

Convertir un data.frame existente en un tibble es bastante sencillo. Basta con colocar nuestro data.frame dentro de as_tibble()[^1].

tbl_notas <- as_tibble(df_notas)

tbl_notas
## # A tibble: 4 x 3
##   matematica lenguaje ciencias
##        <dbl>    <dbl>    <dbl>
## 1         20       18       19
## 2         15       12       14
## 3         17       11       15
## 4         19       19       17

En los tibble, el tipo de columna aparece debajo del encabezado. Esto nos permite tener una idea rápida de la composición de los datos.

Tibbles a partir de listas

Es posible también crear tibbles a partir de listas. Recordemos que originalmente teníamos la lista notas.

notas
## $matematica
## [1] 20 15 17 19
## 
## $lenguaje
## [1] 18 12 11 19
## 
## $ciencias
## [1] 19 14 15 17

Podemos usar as_tibble() directamente en una lista para crear un tibble, sin necesidad de que la lista se convierta primero en un data.frame.

as_tibble(notas)
## # A tibble: 4 x 3
##   matematica lenguaje ciencias
##        <dbl>    <dbl>    <dbl>
## 1         20       18       19
## 2         15       12       14
## 3         17       11       15
## 4         19       19       17

Crear tibbles desde cero

En realidad, no necesitamos crear ningún objeto antes de nuestro tibble. La función tibble() nos permite crearlo directamente, de manera similar a como creamos un data.frame.

tibble(
  enteros = 1:10,
  decimales = enteros/2 
)
## # A tibble: 10 x 2
##    enteros decimales
##      <int>     <dbl>
##  1       1       0.5
##  2       2       1  
##  3       3       1.5
##  4       4       2  
##  5       5       2.5
##  6       6       3  
##  7       7       3.5
##  8       8       4  
##  9       9       4.5
## 10      10       5

Sin embargo, es posible crear un tibble usando una sintaxis diferente con la función tribble().

tribble(
  ~colA, ~colB,
  "a",   1,
  "b",   2,
  "c",   3
)
## # A tibble: 3 x 2
##   colA   colB
##   <chr> <dbl>
## 1 a         1
## 2 b         2
## 3 c         3

La clase tibble

El atributo que ocasiona que un objeto en R se comporte de manera especial es la clase. Además de la clase “data.frame”, los tibble contiene las clases “tbl_df” y “tbl”.

class(tbl_notas)
## [1] "tbl_df"     "tbl"        "data.frame"

Cuando nuestro df es pequeño, ya hemos visto que nos indica el tipo de columna debajo de su encabezado. Si hemos prestado atención, también habremos podido ver que nos muestra sus dimensiones antes del encabezado. Esto es muy útil en los tibble, porque por defecto no imprimen el df completo, sino sólo las diez primeras filas.

Recordemos el df alfabeto, contiene las 26 letras del alfabeto, en mayúsculas en su primera columna y en minúsculas en la segunda. Vamos a crear una versión tibble de este data.frame.

tbl_alfabeto <- as_tibble(alfabeto)

Comparemos cómo son impresos.

# Impresión de data.frame
alfabeto
##    LETTERS letters
## 1        A       a
## 2        B       b
## 3        C       c
## 4        D       d
## 5        E       e
## 6        F       f
## 7        G       g
## 8        H       h
## 9        I       i
## 10       J       j
## 11       K       k
## 12       L       l
## 13       M       m
## 14       N       n
## 15       O       o
## 16       P       p
## 17       Q       q
## 18       R       r
## 19       S       s
## 20       T       t
## 21       U       u
## 22       V       v
## 23       W       w
## 24       X       x
## 25       Y       y
## 26       Z       z

# Impresión de tibble
tbl_alfabeto
## # A tibble: 26 x 2
##    LETTERS letters
##    <chr>   <chr>  
##  1 A       a      
##  2 B       b      
##  3 C       c      
##  4 D       d      
##  5 E       e      
##  6 F       f      
##  7 G       g      
##  8 H       h      
##  9 I       i      
## 10 J       j      
## # ... with 16 more rows

A pesar de que no se imprime el tibble completo, nos da las señales suficientes para saber que contiene 26 filas y dos columnas.

Otra diferencia se da en la inspección de las columnas. Como sabemos, los data.frame imprimen todo su contenido, incluyendo la cantidad total de columnas, en cambio los tibble sólo imprimen las columnas que caben en nuestra pantalla, dando un mensaje informativo al respecto. Veamos el ejemplo del dataset flights, contenido en el paquete nycflights13.

library(nycflights13)

flights
## # A tibble: 336,776 x 19
##     year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
##    <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
##  1  2013     1     1      517            515         2      830            819
##  2  2013     1     1      533            529         4      850            830
##  3  2013     1     1      542            540         2      923            850
##  4  2013     1     1      544            545        -1     1004           1022
##  5  2013     1     1      554            600        -6      812            837
##  6  2013     1     1      554            558        -4      740            728
##  7  2013     1     1      555            600        -5      913            854
##  8  2013     1     1      557            600        -3      709            723
##  9  2013     1     1      557            600        -3      838            846
## 10  2013     1     1      558            600        -2      753            745
## # ... with 336,766 more rows, and 11 more variables: arr_delay <dbl>,
## #   carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
## #   air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

Vemos que es un tibble con 336776 filas y 19 columnas. Por comodidad, el tibble sólo imprimió las diez primeras filas, y las columnas que no alcanzaron en la pantalla están descritas debajo, con su nombre y su tipo.

Ejercicio

Crea tu propio tibble

Ahora es tu turno, recrea el siguiente tibble. Puedes hacerlo usando el método que quieras.

## # A tibble: 4 x 2
##   actor             papel      
##   <chr>             <chr>      
## 1 Leonardo DiCaprio Rick Dalton
## 2 Brad Pitt         Cliff Booth
## 3 Margot Robbie     Sharon Tate
## 4 Emile Hirsch      Jay Sebring