⏱ ≈ 15 min
Bienvenidas y bienvenidos. Aprovechando nuestro tiempo de clase, empecemos por lo práctico: la instalación. Mientras lo hacen, vamos platicando y resolvemos las dudas que surjan.
Si alguien no logra instalar hoy, no pasa nada. La Mini guía de instalación trae los mismos pasos que pueden seguir una vez que termine la clase.
Para el curso es necesario instalar dos herramientas:
Descarga R desde el sitio oficial de R CRAN.
Descarga RStudio desde el sitio oficial de Posit.
Importante: R debe instalarse antes que RStudio, ya que RStudio necesita detectar una instalación de R para funcionar correctamente.
Abre RStudio y, en la consola, escribe lo siguiente:
print("Hola Mundo")
## [1] "Hola Mundo"
Si el programa devuelve la frase en un nuevo renglón, la instalación fue exitosa.
⏱ ≈ 3 min
No asumo que todos saben programación, pero sí asumo que todos pueden aprender a usarla bien. La idea no es memorizar código, vamos a entender cómo funciona, para que después puedan usarlo con seguridad ante cualquier problema al que se enfrenten en sus actividades de análisis.
Desarrollar habilidades de pensamiento analítico utilizando R como herramienta de apoyo para la exploración, análisis e interpretación de datos.
El objetivo no es únicamente aprender comandos o ejecutar instrucciones, sino comprender cómo transformar datos en información útil para la toma de decisiones y la resolución de problemas.
⏱ ≈ 12 min
Antes de abrir nada, una idea clave: R es software libre. Eso quiere decir que la comunidad lo puede enriquecer, y por eso hoy tiene miles de paquetes para casi cualquier tema. Su fuerte son las aplicaciones estadísticas.
Y algo que sí quiero que se lleven desde el inicio: no necesitan ser programadores para usar R, pero sí hay un conjunto básico de conceptos de programación que todo usuario debe entender. De eso trata esta primera sesión.
R es un lenguaje de programación especializado en la manipulación, análisis y visualización de datos.
Es software libre y de código abierto: cualquier persona puede usarlo, revisarlo y mejorarlo.
Es un lenguaje interpretado: escribimos instrucciones en código y R las ejecuta. A diferencia de Excel, no trabajamos con menús y clics.
Actualmente es una de las herramientas más utilizadas en estadística, ciencia de datos, investigación científica, bioestadística, bioinformática y aprendizaje automatizado.
Además de realizar cálculos estadísticos, R permite crear programas, automatizar procesos, generar informes y desarrollar nuevas funciones adaptadas a necesidades específicas.
R es un lenguaje orientado a objetos. Esto significa que la información se organiza en estructuras llamadas objetos, las cuales almacenan datos y permiten trabajar con ellos de manera eficiente.
En R, prácticamente todo es un objeto: números, textos, vectores, tablas de datos, gráficos e incluso funciones.
Cada objeto posee un nombre que permite identificarlo y reutilizarlo durante el análisis.
Por ejemplo:
edad <- 25
En este caso:
edad es el nombre del objeto.25 es el valor almacenado.<- asigna el valor al objeto.En resumen, R es software libre y se define como un entorno integrado para manipular datos, hacer cálculos y generar gráficos. Esa combinación es justamente lo que lo hace tan potente en análisis estadístico.
| Año | Hito |
|---|---|
| Años 70 | Se desarrolla el lenguaje S en Bell Labs (John Chambers). |
| 1993 | Robert Gentleman y Ross Ihaka, de la Universidad de Auckland (Nueva Zelanda), comienzan a desarrollar R. |
| 1995 | El código se libera bajo la licencia GNU GPL. |
| 1997 | Se forma el R Core Team, el grupo que mantiene el lenguaje, y se crea CRAN. |
| 2000 | Sale la primera versión oficial. |
R viene del lenguaje S, que desarrolló John Chambers en Bell Labs en los años 70. De hecho, R puede verse como una versión libre de S, por eso también se le conoce como GNU S. Lo comenzaron Robert Gentleman y Ross Ihaka cuando trabajaban en la Universidad de Auckland, en Nueva Zelanda.
Un par de años después, en 1995, el código se liberó bajo la licencia GNU GPL. GNU es el proyecto de software libre que busca un sistema tipo Unix pero libre, y la GPL, General Public License, es la licencia que garantiza que cualquiera pueda usar y mejorar el software.
Desde 1997 existe el R Core Team, el grupo encargado de mantener y desarrollar el lenguaje. Ese mismo año se creó CRAN, la red mundial donde se alojan R y sus paquetes. La primera versión oficial salió en el año 2000, y desde entonces ha evolucionado muchísimo.
Es común confundir R con RStudio, pero cumplen funciones diferentes.
R es el lenguaje de programación que interpreta y ejecuta nuestras instrucciones.
Cuando escribimos código, R procesa esas instrucciones y realiza tareas como:
Podemos pensar en R como el motor que realiza el trabajo.
RStudio es un entorno de desarrollo integrado (IDE, por sus siglas en inglés) diseñado para trabajar con R de forma más cómoda y organizada.
RStudio proporciona herramientas que facilitan:
Podemos pensar en RStudio como el panel de control que nos permite utilizar el motor R de manera eficiente.
Si pensamos en una cocina:
R sería el chef que realiza el trabajo: prepara los ingredientes, cocina y produce el resultado final. RStudio sería la cocina equipada, con mesas de trabajo, estufa, utensilios y espacio que facilitan la tarea del chef.
Por sí solo, el chef puede cocinar; sin embargo, hacerlo en una cocina bien equipada resulta mucho más cómodo y eficiente.
⏱ ≈ 6 min
Este es el mapa del curso. No hace falta que lo memoricen, pero sí que vean que cada tema se apoya en el anterior.
Aquí vamos a empezar desde cero con el lenguaje. Primero cosas simples: operaciones, variables, tipos de datos… pero esto no es trivial. Si desde el inicio entienden cómo R guarda y procesa información, todo lo demás va a fluir mucho más fácil.
Aquí damos un paso más estructurado. Las matrices nos ayudan a organizar datos numéricos y, sin decirlo todavía en profundidad, nos acercan a la base matemática de muchos modelos.
Aquí ya entramos al mundo real. Los data frames son como las tablas que conocen, pero con más flexibilidad. Aprenderemos a importar datos y empezar a explorarlos de verdad.
Empezamos a trabajar como analistas. Filtrar, agrupar, resumir… básicamente empezar a transformar datos para responder preguntas.
%>%)Aprenderemos a hacer gráficos claros, no solo bonitos, sino que realmente ayuden a entender patrones.
Estructuras más flexibles. Las listas nos permiten guardar casi cualquier cosa, incluso modelos completos.
list()Vamos a usar estas herramientas para construir modelos: algunos clásicos como regresión, y otros más modernos como árboles y random forest.
⏱ ≈ 12 min
Ahora que ya tienen instalado R y RStudio, probablemente se estén preguntando: “Ok, ¿y ahora cómo uso R?”.
Lo primero que deben notar es que, a diferencia de Excel, donde apuntamos y hacemos clic, R es un lenguaje interpretado. Eso significa que debemos escribir comandos en código; es decir, tenemos que programar. Cada línea que escribimos, R la interpreta y la ejecuta. Si algo sale mal, nos va a devolver una advertencia o un mensaje de error, y no pasa nada: los errores son parte de aprender.
Al abrir RStudio por primera vez observaremos que la pantalla está dividida en cuatro áreas principales llamadas paneles. Cada uno cumple una función específica y nos ayuda a organizar nuestro trabajo de análisis de datos.
Ubicado generalmente en la parte superior izquierda.
Es el espacio donde escribimos, editamos y guardamos nuestro código. Trabajar desde scripts nos permite conservar nuestro trabajo y reutilizarlo posteriormente sin tener que volver a escribir las instrucciones.
File > New File > R Script.Ctrl + Enter
(en Mac, Cmd + Enter).#; R no los
ejecuta.El script es nuestra libreta. Y ojo con esto: ¡hay que guardarlo! Si no lo guardan, al cerrar RStudio pierden todo lo que escribieron.
En este curso, la mayor parte del código será escrita en este panel o dentro de documentos R Markdown.
Ubicada normalmente en la parte inferior izquierda.
La consola es el lugar donde R ejecuta nuestras instrucciones. Podemos escribir comandos directamente y obtener resultados de manera inmediata.
Por ejemplo: 2 + 2
La consola también muestra mensajes, advertencias y errores que nos ayudan a comprender lo que está ocurriendo durante la ejecución del código.
Junto a la consola encontramos la pestaña Terminal, que da acceso a la línea de comandos de la computadora. No la utilizaremos en el curso.
La consola es el motor: aquí es donde R ejecuta lo que le pedimos.
Ubicado generalmente en la parte superior derecha.
El panel Environment muestra todos los objetos creados durante la
sesión de trabajo, tales como variables, vectores, tablas de datos y
funciones. Por ejemplo, si ejecutamos a <- 5, el objeto
a aparece aquí. Desde este panel también se pueden importar
conjuntos de datos.
Junto a él encontramos:
Ubicado generalmente en la parte inferior derecha.
Este panel reúne varias herramientas importantes:
Probemos juntos:
2 + 2 y presiona
Enter.a <- 5 y presiona Enter.
Observa que el objeto a aparece en el panel
Environment.a y presiona Enter para ver su
valor.Antes de seguir, una pregunta para el grupo: ¿en qué panel apareció
a? Esa pregunta, y la de cuál panel es el motor, las van a
encontrar en la tarea.
⏱ ≈ 8 min (con las opciones globales)
Un Proyecto es un entorno organizado y reproducible para un análisis. Al abrir un Proyecto, RStudio fija automáticamente el directorio de trabajo en la carpeta del proyecto. Así, los archivos de datos que guardemos ahí se encuentran sin escribir rutas largas.
Para crear uno:
File > New Project > New Directory > New Project.Curso-R) y elige dónde guardarla.Create Project.En esta clase y en las siguientes guardaremos en esa carpeta los archivos de clase y los de datos.
Esto parece un detalle de organización, pero nos va a ahorrar muchos problemas más adelante, cuando importemos archivos y R no los encuentre. Si el directorio de trabajo es la carpeta del proyecto, todo queda a la mano.
En Tools > Global Options se configuran la apariencia
de RStudio, el comportamiento del editor y los intérpretes con los que
trabaja, entre ellos R y Python.
¿Por qué conectar con Python? Algunas APIs o pipelines están hechos en Python. Si existe una herramienta que solo está en Python, la podemos usar sin salir de R. Incluso podemos preparar datos en R y pasar el objeto a Python.
La conexión se hace desde R con una biblioteca y luego se configura qué versión de Python usar: elegir un entorno virtual o ver qué instalación está activa. No lo vamos a usar en el curso, pero es bueno que sepan que existe.
⏱ ≈ 10 min
Piensen en una biblioteca de verdad. Instalar es traer el libro a la biblioteca, y se hace una sola vez. Cargar es sacarlo del estante para usarlo, y se hace cada vez que abrimos R.
Las bibliotecas en R, también conocidas como libraries o paquetes, contienen conjuntos de funciones enfocadas en una misión específica. Éstas amplían la funcionalidad de R al proporcionar funciones adicionales, datos y documentación, y pueden descargarse gratuitamente desde internet. Son desarrolladas por una comunidad mundial de usuarios de R.
Algunas bibliotecas vienen instaladas en R y otras hay que instalarlas manualmente.
Instalar (una sola vez):
Packages,
donde dice Install. Por ejemplo, probemos con
dplyr.install.packages("dplyr").Cargar (cada vez que abrimos R):
library(dplyr).Una vez cargada ya podemos acceder a sus funciones.
Para conocer qué funciones tiene una biblioteca, podemos escribir en la consola:
dplyr:: y explorar la lista que aparece.help(dplyr)?dplyrPara saber qué bibliotecas hemos cargado, podemos consultar la
sección miscelánea o, en la consola, usar la función
search().
install.packages("dplyr")
library(dplyr)
help(dplyr)
?dplyr
search()
Ojo:
install.packages()lleva el nombre entre comillas ylibrary()no.
Durante el curso usaremos los siguientes paquetes. Instálalos una sola vez, antes de la clase 2:
install.packages(c("readxl", "openxlsx", "babynames", "dplyr",
"ggplot2", "patchwork", "performance",
"see", "titanic",
"rpart.plot", "randomForest"))
Otros paquetes que vamos a usar en el curso como MASS y rpart ya vienen con R, por eso no aparecen en la lista. Esta instalación puede tardar varios minutos. Si no terminan en clase, pueden terminarla en casa antes de la clase 2.
⏱ ≈ 5 min
Las actividades del curso se desarrollarán en archivos R Markdown, un formato que permite combinar texto, código, resultados y gráficos en un único documento reproducible. Esta metodología facilita la documentación del análisis y favorece buenas prácticas de trabajo en ciencia de datos.
| Elemento | Sintaxis / Atajo |
|---|---|
| Título principal | # Título |
| Sección | ## Sección |
| Subsección | ### Subsección |
| Negrita | **texto** |
| Cursiva | *texto* |
| Lista | - Elemento |
| Nota | > Nota importante |
| Enlace | [Texto](https://sitio.com) |
| Separador | *** |
| Chunk de código R | Ctrl + Alt + I |
| Comentar / descomentar líneas | Ctrl + Shift + C |
| Compilar el documento (Knit) | Ctrl + Shift + K |
No es necesario memorizar esta sintaxis, se volverá familiar con la práctica.
⏱ ≈ 22 min
Aquí empieza lo que no es trivial. Si entienden qué tipo de dato es cada cosa, van a evitar muchísimos errores más adelante.
1L
## [1] 1
# La L viene de Long integer
# Señala que el número debe interpretarse como un entero (integer) y no como un valor de doble precisión (double).
Comentarios en R: Usamos
#para agregar notas o explicaciones dentro de los chunks de código. Los comentarios no son ejecutados por R.
1.53
## [1] 1.53
pi
## [1] 3.141593
numeric(length = 5)
## [1] 0 0 0 0 0
'Hola'
## [1] "Hola"
"Hola"
## [1] "Hola"
character(length = 2)
## [1] "" ""
Existen objetos que pueden almacenar más de un valor. La función
c() permite combinar elementos en un vector.
c(1,2)
## [1] 1 2
c("Hola","amigo")
## [1] "Hola" "amigo"
Esto es solo un adelanto: después del descanso vemos los vectores con todo detalle.
Normalmente se describen como datos numéricos pero almacenan datos categóricos (variables cualitativas).
factor(c("mujer","mujer","mujer","hombre"))
## [1] mujer mujer mujer hombre
## Levels: hombre mujer
Levels ayuda a clasificar categorías que incluso podrían no estar en la muestra.
factor(c("mujer","mujer","mujer","mujer"),levels=c("hombre","mujer"))
## [1] mujer mujer mujer mujer
## Levels: hombre mujer
Labels permite modificar los nombres de los niveles de factores.
factor(c("mujer","mujer","mujer","mujer"),levels=c("hombre","mujer"),labels=c("H","M"))
## [1] M M M M
## Levels: H M
Pueden no tener un orden.
# 0 Estudiante
# 1 Profesor
factor(c(0,1))
## [1] 0 1
## Levels: 0 1
O sí…
factor(c(1,2,3))
## [1] 1 2 3
## Levels: 1 2 3
factor(c("Bajo","Medio","Alto"))
## [1] Bajo Medio Alto
## Levels: Alto Bajo Medio
R ordena los niveles alfabéticamente, no por sentido. Miren el orden en que aparecen los niveles: “Alto” queda antes que “Bajo”. Es justo lo que vamos a corregir.
factor(
c("Bajo","Medio","Alto"),
levels = c("Bajo","Medio","Alto"),
ordered = TRUE
)
## [1] Bajo Medio Alto
## Levels: Bajo < Medio < Alto
# R interpreta: Bajo < Medio < Alto
Se basan principalmente en dos valores: TRUE (verdadero)
y FALSE (falso). Pueden abreviarse como T y
F (no recomendable), y se obtienen mediante comparaciones
lógicas.
TRUE
## [1] TRUE
FALSE
## [1] FALSE
2<3
## [1] TRUE
3<2
## [1] FALSE
¿Por qué no es recomendable abreviar? Porque T y
F son variables que R define por nosotros, y se pueden
sobrescribir:
T <- FALSE
T
## [1] FALSE
# Eliminamos nuestra versión para que T vuelva a significar TRUE
rm(T)
T
## [1] TRUE
NA # not available
## [1] NA
NULL # no definido
## NULL
Las definiremos en formato AAAA-MM-DD.
as.Date("2026-02-17")
## [1] "2026-02-17"
A través de class() podemos determinar qué tipo de dato
es un objeto.
Esto es útil cuando tenemos que verificar la entrada que se pasa a una función escrita por nosotros y así evitar que se pasen objetos de un tipo incorrecto.
class(8L)
## [1] "integer"
class(99)
## [1] "numeric"
class("Hola")
## [1] "character"
class(factor(c(1,2)))
## [1] "factor"
class(FALSE)
## [1] "logical"
class("2026-02-17")
## [1] "character"
class(as.Date("2026-02-17"))
## [1] "Date"
class(T)
## [1] "logical"
Advertencia: El valor
"2026-02-17"no es una fecha para R, sino una cadena de texto. Para trabajar con fechas debe convertirse al tipoDateusandoas.Date("2026-02-17").
Y se puede preguntar por un tipo de datos en particular. La respuesta será un dato tipo lógico.
# ¿Es entero?
is.integer(1)
## [1] FALSE
is.integer(1L)
## [1] TRUE
# ¿Qué es pi?
is.integer(pi)
## [1] FALSE
is.numeric(pi)
## [1] TRUE
# ¿Es texto?
is.character(1)
## [1] FALSE
is.character('1')
## [1] TRUE
# ¿Lógicos?
isTRUE(3<1)
## [1] FALSE
isTRUE(TRUE)
## [1] TRUE
isTRUE(T)
## [1] TRUE
isTRUE(F)
## [1] FALSE
isFALSE(FALSE)
## [1] TRUE
# ¿Factores o perdidos?
is.factor(c(1,2))
## [1] FALSE
is.factor(factor(c(1,2)))
## [1] TRUE
is.na(NA)
## [1] TRUE
is.null(NULL)
## [1] TRUE
# ¿Fechas?
# is.Date no existe :c
is(as.Date("2026-02-17"),"Date")
## [1] TRUE
Al ejecutar una operación, R intentará transformar el tipo de dato original al tipo que permita realizar la operación.
Sin embargo, si este proceso falla obtendremos un error.
Antes de correr el chunk: ¿qué creen que devuelve
TRUE + TRUE? ¿Y de qué clase es el resultado? Piénsenlo y
lo comprobamos.
TRUE + TRUE
## [1] 2
class(TRUE)
## [1] "logical"
class(TRUE+TRUE)
## [1] "integer"
TRUE / TRUE
## [1] 1
class(TRUE/TRUE)
## [1] "numeric"
paste(TRUE/TRUE,"si")
## [1] "1 si"
class(paste(TRUE/TRUE,"si"))
## [1] "character"
Aquí el programador convierte manualmente el dato usando funciones específicas.
# Coerción explícita numérica
as.integer(FALSE)
## [1] 0
as.integer('3')
## [1] 3
class(as.integer('3'))
## [1] "integer"
# as.integer("tres")
# Coerción explícita cadena
as.character(TRUE)
## [1] "TRUE"
as.character(3)
## [1] "3"
# Coerción explícita lógica
as.logical(1)
## [1] TRUE
as.logical(3)
## [1] TRUE
as.logical(-1)
## [1] TRUE
as.logical(0) # solo este regresa FALSE
## [1] FALSE
as.logical("true")
## [1] TRUE
as.logical("false")
## [1] FALSE
# Coerción explícita factor
as.factor(c(1,2))
## [1] 1 2
## Levels: 1 2
as.factor("hola")
## [1] hola
## Levels: hola
⏱ ≈ 20 min
Los usamos en tipos de dato enteros o numéricos.
| Operador | Operación | Ejemplo |
|---|---|---|
+ |
suma | 3 + 2 |
- |
resta | 3 - 2 |
* |
multiplicación | 3 * 2 |
/ |
división | 3 / 2 |
^ |
potencia | 2^3 |
%/% |
división entera | 45 %/% 4 |
%% |
módulo (residuo de la división) | 38 %% 6 |
2^3
## [1] 8
45/4
## [1] 11.25
45 %/% 4
## [1] 11
38/6
## [1] 6.333333
38 %% 6
## [1] 2
Se aplica la regla nemotécnica PEMDAS: Paréntesis, Exponentes, Multiplicación y División (izquierda a derecha), y Adición/Suma y Sustracción/Resta (izquierda a derecha).
(4*6)+2
## [1] 26
4*(6+2)
## [1] 32
4+6*2
## [1] 16
TRUE + 4
## [1] 5
FALSE * 9
## [1] 0
2 + NA
## [1] NA
7 / 0
## [1] Inf
-3 / 0
## [1] -Inf
# 'tres' + 2
Devuelven un tipo de dato lógico luego de hacer comparaciones.
2 < 3 # ¿menor que?
## [1] TRUE
2 > 3 # ¿mayor que?
## [1] FALSE
2 <= 3 # ¿menor o igual que?
## [1] TRUE
3 >= 3 # ¿mayor o igual que?
## [1] TRUE
2 == 3 # ¿iguales?
## [1] FALSE
2 != 3 # ¿distintos?
## [1] TRUE
Nota: Los operadores relacionales también comparan cadenas de texto siguiendo el orden alfabético. El resultado de comparar mayúsculas con minúsculas (por ejemplo,
"A" < "a") depende del idioma y de la configuración regional del sistema, por lo que puede variar de una computadora a otra.
"A" < "a"
## [1] FALSE
El último resultado puede variar de una computadora a otra: la comparación de mayúsculas y minúsculas depende del idioma y la configuración regional del sistema. Comparen sus resultados entre ustedes.
& significa “y” (conjunción)Sean P y Q dos proposiciones o condiciones, entonces:
| P | Q | P & Q |
|---|---|---|
| TRUE | TRUE | TRUE |
| TRUE | FALSE | FALSE |
| FALSE | TRUE | FALSE |
| FALSE | FALSE | FALSE |
Notemos que una conjunción es verdadera únicamente cuando ambas condiciones se cumplen o son verdaderas, en cualquier otro caso es falsa.
TRUE & FALSE
## [1] FALSE
3 < 1 & 4 > 2
## [1] FALSE
| significa “o” (disyunción)Sean P y Q dos proposiciones o condiciones, entonces:
| P | Q | P | Q |
|---|---|---|
| TRUE | TRUE | TRUE |
| TRUE | FALSE | TRUE |
| FALSE | TRUE | TRUE |
| FALSE | FALSE | FALSE |
Una disyunción es verdadera siempre y cuando al menos una de las proposiciones o condiciones sea verdadera, por otro lado, solo es falsa si ambas condiciones lo son.
TRUE | FALSE
## [1] TRUE
3 < 1 | 4 > 2
## [1] TRUE
! significa “no” (negación).Al aplicar este operador se cambia el valor guardado en una variable lógica. Sea P una proposición o condición, entonces:
| P | !P |
|---|---|
| TRUE | FALSE |
| FALSE | TRUE |
!TRUE
## [1] FALSE
!( 3 < 1)
## [1] TRUE
&& y doble ||Los operadores & y | trabajan
elemento a elemento: si les damos vectores, devuelven
un resultado por cada posición. En cambio, && y
|| evalúan un solo valor y se detienen en
cuanto ya saben la respuesta (por eso se les llama operadores de
cortocircuito).
# Elemento a elemento: un resultado por cada posición
c(TRUE, FALSE, TRUE) & c(TRUE, TRUE, FALSE)
## [1] TRUE FALSE FALSE
# Un solo valor
TRUE && FALSE
## [1] FALSE
TRUE || FALSE
## [1] TRUE
Si el lado izquierdo ya decide el resultado, R no evalúa el lado derecho:
exists("variable_que_no_existe") && variable_que_no_existe > 3
## [1] FALSE
# Con un solo & sí se evalúan ambos lados, y marca error:
# exists("variable_que_no_existe") & variable_que_no_existe > 3
Importante:
&&y||están hechos para condiciones de un solo valor. En las versiones recientes de R (4.3 o posteriores), usarlos con vectores de más de un elemento produce un error.
La regla práctica: si trabajan con vectores, usen &
y |. Si trabajan con una sola condición,
&& y || son los indicados. En este
curso casi siempre usaremos los simples.
Para resumir un vector lógico en un solo valor contamos con
any() (“¿al menos uno es verdadero?”) y all()
(“¿todos son verdaderos?”):
any(c(FALSE, TRUE, FALSE))
## [1] TRUE
all(c(TRUE, TRUE, FALSE))
## [1] FALSE
Al programar es importante asignar variables pues esto nos permite guardar la información para poder realizar operaciones.
Existen varias formas de crear variables:
a = 6a <- 6 es la forma más usada por convención del
lenguaje R6 -> aassign("a", 6)a <- b <- 6Después de correr estas líneas de código, las variables quedan guardadas en nuestro espacio de trabajo.
dado <- 6
dado
## [1] 6
dado2 <- 2
dado2
## [1] 2
5 -> dado3
dado3
## [1] 5
dado + dado2
## [1] 8
dado <- dado2 <- dado3 <- 25
dado2
## [1] 25
assign("dado",1000)
dado
## [1] 1000
exists("dado3")
## [1] TRUE
rm(dado3)
exists("dado3")
## [1] FALSE
ls()
## [1] "dado" "dado2" "edad"
rm(list=ls())
ls()
## character(0)
⏱ ≈ 2 min
Y bueno, con esto cerramos la primera parte: ya instalaron, ya saben dónde escribir y dónde se ejecuta R, y vieron cómo guarda y procesa la información. Si algo no les quedó claro, no se preocupen, lo vamos a seguir usando. Tomemos un descanso de 10 minutos y, al regresar, pasamos de un solo valor a muchos: vectores.
☕ Descanso de 10 min
⏱ ≈ 10 min
Volvemos del descanso. Antes de entrar a vectores, apliquemos lo que acabamos de ver con un caso que les va a sonar: calcular la prima de un seguro de vida. Para esto vamos a usar tipos de datos y operadores lógicos.
Una aseguradora está evaluando la prima anual de un seguro de vida individual. Para simplificar, se utilizará un modelo aproximado donde:
La información del cliente es:
Instrucciones
nombre <- "María"
edad <- 47
suma_asegurada <- 1200000
anios_cliente <- 8
reclamaciones <- 1
fumador <- FALSE
class(nombre)
## [1] "character"
class(edad)
## [1] "numeric"
class(suma_asegurada)
## [1] "numeric"
class(anios_cliente)
## [1] "numeric"
class(reclamaciones)
## [1] "numeric"
class(fumador)
## [1] "logical"
perfil_alto_riesgo que
indique si la persona asegurada presenta al menos dos condiciones de
riesgo. Consideramos condiciones de riesgo una edad mayor a 45 años, ser
fumador, y haber presentado reclamaciones médicas previas.edad > 45
## [1] TRUE
isTRUE(fumador)
## [1] FALSE
reclamaciones > 0
## [1] TRUE
# Primer intento: con "|" solo sabemos si se cumple AL MENOS UNA condición
perfil_alto_riesgo <- (edad > 45) | (isTRUE(fumador)) | (reclamaciones > 0)
perfil_alto_riesgo
## [1] TRUE
# Segundo intento: sumamos las condiciones
perfil_alto_riesgo <- (edad > 45) + (isTRUE(fumador)) + (reclamaciones > 0)
perfil_alto_riesgo
## [1] 2
class(perfil_alto_riesgo)
## [1] "integer"
# Ahora sí: al menos dos condiciones
perfil_alto_riesgo <- ((edad > 45) + (isTRUE(fumador)) + (reclamaciones > 0)) >= 2
perfil_alto_riesgo
## [1] TRUE
class(perfil_alto_riesgo)
## [1] "logical"
Ojo con los tres intentos. Con | solo sabemos si se
cumple al menos una condición, y lo que queremos es al menos dos. Por
eso sumamos las condiciones: TRUE vale 1 y FALSE vale 0 (coerción
implícita), así que la suma cuenta cuántas condiciones se cumplen.
Por eso en Environment aparece el valor 2L: sumar lógicos devuelve un
entero, y la L nos lo indica. Al comparar con >= 2
volvemos a tener un valor lógico.
isTRUE() nos asegura un solo TRUE o FALSE. Y con valores
sueltos, | y || darían lo mismo; la diferencia
se ve con vectores, y eso lo vemos más adelante en esta clase.
prima_base <- 0.02 * suma_asegurada
recargo <- perfil_alto_riesgo * 0.10
class(recargo)
## [1] "numeric"
descuento <- (anios_cliente > 5) * 0.03
prima_final <- prima_base * (1 + recargo - descuento)
prima_base; recargo; descuento; prima_final
## [1] 24000
## [1] 0.1
## [1] 0.03
## [1] 25680
Opcional, si el tiempo lo permite.
Una pregunta que puede surgir es: ¿por qué no hacemos
prima_base * (1 + recargo) * (1 - descuento)? Veamos cuánto
pesa el descuento en cada esquema respecto a la prima base.
# Esquema multiplicativo: el descuento se aplica sobre la prima ya recargada
prima_mult <- prima_base * (1 + recargo) * (1 - descuento)
# Esquema lineal: recargo y descuento se aplican sobre la prima base
prima_lin <- prima_base * (1 + recargo - descuento)
# ¿Qué tan grande es el descuento efectivo respecto a la prima base?
(prima_base * (1 + recargo) - prima_mult) / prima_base * 100 # multiplicativo
## [1] 3.3
(prima_base * (1 + recargo) - prima_lin) / prima_base * 100 # lineal
## [1] 3
Dividimos entre la prima base porque queremos medir el impacto del descuento respecto al monto original; si dividiéramos entre la prima recargada, obtendríamos exactamente el 3% contractual.
En el esquema multiplicativo, el descuento se aplica sobre una prima ya incrementada por el recargo, y eso genera una tasa efectiva de descuento ligeramente mayor al 3% (alrededor de 3.3%). Dado que tanto el recargo como el descuento deben aplicarse sobre la prima base, utilizamos el modelo lineal.
⏱ ≈ 3 min
Piensen en estas cuatro estructuras como cuatro formas de organizar la información, de la más simple a la más flexible. Hoy empezamos por la más básica: los vectores.
En R, toda la información se almacena en objetos. Dependiendo de cómo estén organizados los datos, estos objetos pueden adoptar distintas estructuras. Existen cuatro estructuras principales en R:
Comenzaremos con la estructura más básica y fundamental en R: los vectores.
⏱ ≈ 40 min
Recuerden el adelanto que vimos hace un rato con c():
ahora sí vemos los vectores con todo detalle.
Un vector en R es una colección ordenada de datos. Esta estructura almacena una secuencia de elementos del mismo tipo, es decir, los vectores pueden tener elementos numéricos, caracteres, lógicos, etc.
Para crear un vector se utiliza la función c() que puede
tener un número arbitrario de datos.
En R, los vectores permiten guardar conjuntos de valores numéricos y hacer operaciones con todos ellos al mismo tiempo.
En cálculo actuarial, por ejemplo, si las probabilidades de que una persona de edad x sobreviva k años se almacenan en un vector, la esperanza de vida discreta puede obtenerse simplemente sumando esos valores. Así, los vectores facilitan hacer cálculos actuariales de forma directa y ordenada, sin tener que trabajar elemento por elemento.
Tipo de dato y clase: En R, los vectores son atómicos por definición: esto significa que todas sus entradas deben ser del mismo tipo de dato (logical, numeric, character, etc.).
Cuando intentamos combinar distintos tipos de datos en un mismo vector, R aplica coerción implícita para convertir todos los elementos al tipo más general en la jerarquía logical → integer → double → character.
vector1 <- c(1,2,3,4,5)
vector1
## [1] 1 2 3 4 5
class(vector1)
## [1] "numeric"
is.vector(vector1)
## [1] TRUE
is.numeric(vector1)
## [1] TRUE
vector2 <- c(1,2,"hola",4,5)
vector2
## [1] "1" "2" "hola" "4" "5"
# predomina el tipo de dato character por la coerción implícita
class(vector2)
## [1] "character"
is.vector(vector2)
## [1] TRUE
is.numeric(vector2)
## [1] FALSE
is.character(vector2)
## [1] TRUE
edades <- c(20,25,29,32,"8s",21)
edades
## [1] "20" "25" "29" "32" "8s" "21"
mean(edades)
## Warning in mean.default(edades): argument is not numeric or logical: returning
## NA
## [1] NA
# Warning: el vector se convirtió a character
# y mean() solo opera sobre datos numéricos
class(edades)
## [1] "character"
Dos ideas clave. Primera: un vector solo guarda un tipo de dato.
Segunda: si mezclamos, R convierte todo al tipo más general, siguiendo
la jerarquía lógico, entero, double y carácter. Por eso un solo “8s”
convierte todas las edades en texto, y mean() ya no puede
calcular nada. Es un error muy común cuando importamos datos.
Largo: es el número de elementos que contiene un
vector. Es la única dimensión que tiene un vector. Para calcular el
largo se utiliza la función length().
vector1
## [1] 1 2 3 4 5
length(vector1)
## [1] 5
edades; length(edades)
## [1] "20" "25" "29" "32" "8s" "21"
## [1] 6
Los vectores pueden usarse para realizar operaciones aritméticas. Estas operaciones se realizan elemento a elemento.
vector3 <- c(1,3,5,7,9)
vector4 <- c(2,4,6,8,10)
# Suma
vector_suma <- vector3 + vector4
vector_suma # autoprint
## [1] 3 7 11 15 19
# Resta
vector_resta <- vector3 - vector4
print(vector_resta)
## [1] -1 -1 -1 -1 -1
# Producto
vector_producto <- vector3 * vector4
print(vector_producto)
## [1] 2 12 30 56 90
# División
vector_division <- vector3 / vector4
print(vector_division)
## [1] 0.5000000 0.7500000 0.8333333 0.8750000 0.9000000
# Potencia
vector_potencia <- vector3 ^ vector4
print(vector_potencia)
## [1] 1 81 15625 5764801 3486784401
Elemento a elemento quiere decir: la posición 1 con la 1, la 2 con la 2, y así. No tenemos que recorrer el vector nosotros.
En R, muchas operaciones están vectorizadas. Esto significa que una operación aplicada a un vector se realiza automáticamente sobre cada uno de sus elementos, sin necesidad de utilizar ciclos o bucles.
salarios <- c(8000, 9000, 10000, 15000)
salarios
## [1] 8000 9000 10000 15000
# Aumento salarial del 5%
salarios * 1.05
## [1] 8400 9450 10500 15750
salarios
## [1] 8000 9000 10000 15000
# Bono fijo de $500
salarios + 500
## [1] 8500 9500 10500 15500
salarios
## [1] 8000 9000 10000 15000
## Cada elemento del vector recibe el aumento de forma automática
Fíjense que salarios no cambia: la operación nos
devuelve un resultado nuevo, y el original queda igual. Si queremos
conservar el resultado, hay que asignarlo a una variable o reasignarlo a
salarios.
¿Qué ocurre cuando aplicamos operadores entre vectores de distinta longitud?
Antes de correr el chunk: x tiene 5 elementos e
y tiene 3. ¿Qué creen que va a pasar al multiplicarlos?
¿Cuántos elementos tendrá el resultado?
x <- c(1,1,1,1,1)
x
## [1] 1 1 1 1 1
y <- c(2,3,4)
y
## [1] 2 3 4
length(x)
## [1] 5
length(y)
## [1] 3
x * y
## Warning in x * y: longitud de objeto mayor no es múltiplo de la longitud de uno
## menor
## [1] 2 3 4 2 3
# Warning:
# longer object length is not a multiple of shorter object length
Un warning no detiene la ejecución del código; simplemente alerta sobre una situación que podría producir resultados inesperados.
R aplica la regla de reciclaje (recycling rule): repite los elementos del vector más corto hasta completar la longitud del más largo.
Idealmente, la longitud del vector más largo debe ser múltiplo de la del más corto. Si no lo es (como en este ejemplo, 5 no es múltiplo de 3), R realiza la operación pero muestra un warning, porque el reciclaje no es exacto.
Existen funciones matemáticas como log(),
exp(), sin(), cos(),
tan() y sqrt().
También hay funciones estadísticas y de resumen como
min(), max(), sum(),
prod(), mean(), median(),
var() y sd(). Éstas devuelven un único valor a
partir del vector.
Asimismo, existen funciones de ordenamiento y resumen descriptivo,
como sort(), rev() y
summary().
salarios <- c(15000, 9000, 10000, 8000)
salarios
## [1] 15000 9000 10000 8000
min(salarios)
## [1] 8000
max(salarios)
## [1] 15000
sum(salarios)
## [1] 42000
prod(salarios)
## [1] 1.08e+16
mean(salarios)
## [1] 10500
median(salarios)
## [1] 9500
var(salarios)
## [1] 9666667
sd(salarios)
## [1] 3109.126
salarios
## [1] 15000 9000 10000 8000
sort(salarios)
## [1] 8000 9000 10000 15000
salarios; rev(salarios)
## [1] 15000 9000 10000 8000
## [1] 8000 10000 9000 15000
# salarios <- rev(salarios)
summary(salarios)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 8000 8750 9500 10500 11250 15000
Aquí la que más nos interesa para lo que sigue es
median(). La media se mueve mucho con valores extremos; la
mediana no. Prueben cambiar el 15000 por 150000 y comparen cómo
reacciona cada una.
Si el vector contiene valores NA, debemos agregar un
argumento adicional para que la función los ignore en el cálculo.
salarios_na <- c(8000, 9000, 10000, 15000, NA)
class(salarios_na)
## [1] "numeric"
mean(salarios_na)
## [1] NA
mean(salarios_na, na.rm = TRUE)
## [1] 10500
nombres <- c("Adrian","Cintia","Keyla","Diego")
print(nombres); class(nombres)
## [1] "Adrian" "Cintia" "Keyla" "Diego"
## [1] "character"
edades <- c(18,20,22,29)
vector_combinado <- paste(nombres, edades)
print(vector_combinado)
## [1] "Adrian 18" "Cintia 20" "Keyla 22" "Diego 29"
vector_combinado <- paste(nombres,", su edad es:", edades)
print(vector_combinado)
## [1] "Adrian , su edad es: 18" "Cintia , su edad es: 20"
## [3] "Keyla , su edad es: 22" "Diego , su edad es: 29"
⏱ ≈ 28 min
En R, los “vectores con índices” se refiere a la forma de acceder y manipular a los elementos individuales de un vector mediante índices numéricos.
Cada elemento en un vector tiene una posición única que se identifica mediante un índice numérico. Estos comienzan desde 1 hasta la longitud del vector.
En R los índices comienzan en 1, no en 0 como ocurre en muchos lenguajes de programación.
vec <- c(10,20,30,40,50)
# Recuperamos el 3er elemento del vector
elemento <- vec[3]
print(elemento)
## [1] 30
# Reasignamos valores por posición
vec[3] <- 33
print(vec)
## [1] 10 20 33 40 50
class(vec)
## [1] "numeric"
vec[3] <- "Hola"
class(vec)
## [1] "character"
print(vec)
## [1] "10" "20" "Hola" "40" "50"
Podemos indicar varias posiciones con c() y darles sus
nuevos valores, también con c(). El primer valor va a la
primera posición indicada, el segundo a la segunda, y así
sucesivamente.
precios <- c(100, 200, 300, 400)
# La posición 2 recibe 250 y la posición 4 recibe 450
precios[c(2, 4)] <- c(250, 450)
precios
## [1] 100 250 300 450
salarios <- c(15000, 9000, 10000, 8000)
salarios
## [1] 15000 9000 10000 8000
salarios <- sort(salarios)
salarios
## [1] 8000 9000 10000 15000
# 3 salarios más bajos
salarios[1]; salarios[2]; salarios[3]
## [1] 8000
## [1] 9000
## [1] 10000
salarios[c(1,2,3)]
## [1] 8000 9000 10000
# Secuencias numéricas con el operador ":"
salarios[1:3]
## [1] 8000 9000 10000
length(salarios[1:3])
## [1] 3
salarios[2:4]
## [1] 9000 10000 15000
# La longitud de un vector de tipo a:b será b-a+1
length(salarios[2:4])
## [1] 3
4 - 2 + 1
## [1] 3
En este caso, indican los elementos del vector referido que deben ser excluidos.
Antes de correr el chunk: ¿qué creen que devuelve
salarios[-1]? ¿Y salarios[-(2:4)]?
salarios; salarios[-1]
## [1] 8000 9000 10000 15000
## [1] 9000 10000 15000
salarios; salarios[-(2:4)]
## [1] 8000 9000 10000 15000
## [1] 8000
Solo se mostrarán los elementos que cumplan una condición lógica como índice.
Antes de correr el chunk: ¿qué creen que devuelve
salarios > 10000? ¿Y qué pasa si usamos ese resultado
dentro de los corchetes?
salarios
## [1] 8000 9000 10000 15000
salarios > 10000
## [1] FALSE FALSE FALSE TRUE
salarios[salarios > 10000]
## [1] 15000
Como un vector lógico está hecho de TRUE y
FALSE, y R los trata como 1 y 0, con sum()
podemos contar cuántos elementos cumplen una
condición.
# ¿Cuántos salarios superan los 10,000?
sum(salarios > 10000)
## [1] 1
Con & (“y”) y | (“o”) podemos combinar
varias condiciones sobre el vector completo. Estos operadores trabajan
elemento a elemento.
# Salarios mayores a 9,000 Y menores a 15,000
salarios[(salarios > 9000) & (salarios < 15000)]
## [1] 10000
# Salarios menores a 9,000 O mayores a 12,000
salarios[(salarios < 9000) | (salarios > 12000)]
## [1] 8000 15000
Aquí es donde se nota la diferencia que vimos antes del descanso.
Para combinar condiciones sobre un vector necesitamos &
y |, que comparan posición por posición. Con
&& o || esto marcaría un error, porque
esos operadores solo evalúan un valor.
Y no se olviden de los paréntesis alrededor de cada condición: nos evitan errores de jerarquía y hacen el código más fácil de leer.
En la práctica, casi todas las bases de datos traen valores faltantes. Veremos dos caminos: eliminarlos o imputarlos. Ninguno es gratis: si eliminamos, perdemos observaciones; si imputamos con la media, reducimos la variabilidad de los datos.
En la práctica, las bases de datos suelen contener valores faltantes
(NA). Por ejemplo, algunos clientes pueden no reportar su
salario, edad o antigüedad laboral.
NAPodemos usar indexación lógica y reasignación para eliminar los
valores NA del vector.
salarios <- c(8000, 9000, 10000, 15000, NA, NA)
is.na(salarios)
## [1] FALSE FALSE FALSE FALSE TRUE TRUE
!is.na(salarios)
## [1] TRUE TRUE TRUE TRUE FALSE FALSE
salarios[!is.na(salarios)]
## [1] 8000 9000 10000 15000
salarios <- salarios[!is.na(salarios)]
salarios
## [1] 8000 9000 10000 15000
sd(salarios)
## [1] 3109.126
NAOtra alternativa es reemplazar estos valores faltantes por una estimación razonable basada en la información disponible. A este proceso se le conoce como imputación y evita eliminar observaciones completas.
salarios <- c(8000, 9000, 10000, 15000, NA, NA)
salarios
## [1] 8000 9000 10000 15000 NA NA
# Identificamos las posiciones NA
is.na(salarios)
## [1] FALSE FALSE FALSE FALSE TRUE TRUE
which(is.na(salarios))
## [1] 5 6
posiciones_NA <- which(is.na(salarios))
posiciones_NA
## [1] 5 6
# Reemplazamos a los NA por la media
salarios
## [1] 8000 9000 10000 15000 NA NA
media_salarios <- mean(salarios, na.rm = TRUE)
media_salarios
## [1] 10500
salarios[posiciones_NA] <- media_salarios
salarios
## [1] 8000 9000 10000 15000 10500 10500
⏱ ≈ 8 min
La función seq() permite generar secuencias más
complejas. Esta función dispone de cinco argumentos, aunque no todos se
utilizan simultáneamente.
seq(from = 1, to = 10)
## [1] 1 2 3 4 5 6 7 8 9 10
length(seq(from = 1, to = 10))
## [1] 10
class(seq(from = 1, to = 10))
## [1] "integer"
is.vector(seq(from = 1, to = 10))
## [1] TRUE
seq(from = 1, to = 10, by = 2)
## [1] 1 3 5 7 9
seq(1, 10, length.out = 20) # seq(1, 10, length = 20)
## [1] 1.000000 1.473684 1.947368 2.421053 2.894737 3.368421 3.842105
## [8] 4.315789 4.789474 5.263158 5.736842 6.210526 6.684211 7.157895
## [15] 7.631579 8.105263 8.578947 9.052632 9.526316 10.000000
a <- 1:5
a
## [1] 1 2 3 4 5
length(a)
## [1] 5
b <- seq(from = 14, along.with = a) # seq(from = 14, along = a)
a; b
## [1] 1 2 3 4 5
## [1] 14 15 16 17 18
is.element(1,a)
## [1] TRUE
is.element(1,b)
## [1] FALSE
La función rep() también es útil para generar patrones
repetitivos en secuencias.
rep(c(4,6,1), times = 3)
## [1] 4 6 1 4 6 1 4 6 1
length(rep(c(4,6,1), times = 3))
## [1] 9
⏱ ≈ 15 min
Ahora les toca a ustedes. Denles unos minutos a cada ejercicio y luego lo resolvemos juntos.
seq().seq(from = 2, to = 20, by = 2)
## [1] 2 4 6 8 10 12 14 16 18 20
seq(from = 0, to = 1, by = 0.1)
## [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
(1:10)^2
## [1] 1 4 9 16 25 36 49 64 81 100
(1:100) %% 3 == 0
## [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [13] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [25] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [37] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [49] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [61] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [73] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [85] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE
## [97] FALSE FALSE TRUE FALSE
(1:100)[(1:100) %% 3 == 0]
## [1] 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75
## [26] 78 81 84 87 90 93 96 99
seq(from = 3, to = 100, by = 3)
## [1] 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75
## [26] 78 81 84 87 90 93 96 99
seq(from = as.Date("2026-02-01"), to = as.Date("2026-02-28"), by = "day")
## [1] "2026-02-01" "2026-02-02" "2026-02-03" "2026-02-04" "2026-02-05"
## [6] "2026-02-06" "2026-02-07" "2026-02-08" "2026-02-09" "2026-02-10"
## [11] "2026-02-11" "2026-02-12" "2026-02-13" "2026-02-14" "2026-02-15"
## [16] "2026-02-16" "2026-02-17" "2026-02-18" "2026-02-19" "2026-02-20"
## [21] "2026-02-21" "2026-02-22" "2026-02-23" "2026-02-24" "2026-02-25"
## [26] "2026-02-26" "2026-02-27" "2026-02-28"
seq(from = as.Date("2026-02-01"), to = as.Date("2026-02-28"), by = 2)
## [1] "2026-02-01" "2026-02-03" "2026-02-05" "2026-02-07" "2026-02-09"
## [6] "2026-02-11" "2026-02-13" "2026-02-15" "2026-02-17" "2026-02-19"
## [11] "2026-02-21" "2026-02-23" "2026-02-25" "2026-02-27"
⏱ ≈ 3 min
Y bueno, esto fue bastante para una sola clase, pero lo importante es lo que nos llevamos: R ya no les suena a algo raro. Ya lo instalaron, saben dónde escribir y dónde se ejecuta, vieron cómo guarda y procesa la información, y además ya no pensamos en un solo dato, sino en conjuntos de datos: saben crear vectores, operar con todos sus elementos a la vez, sacar justo los que necesitan con los índices y generar secuencias. Es una de las ideas más potentes de R, y todo lo que sigue se apoya en esto. Si algo todavía no les queda claro, no se preocupen, esto se vuelve familiar con la práctica y lo vamos a seguir usando todo el curso. En la próxima clase pasamos de una sola fila de datos a un arreglo con filas y columnas: las matrices, y de ahí a las tablas de datos, los data frames.