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
perfil_alto_riesgo <- (edad > 45) | (isTRUE(fumador)) | (reclamaciones > 0)
perfil_alto_riesgo
## [1] TRUE
perfil_alto_riesgo <- (edad > 45) + (isTRUE(fumador)) + (reclamaciones > 0)
perfil_alto_riesgo
## [1] 2
class(perfil_alto_riesgo)
## [1] "integer"
# En Environment, aparece el valor de 2L porque estamos
# sumando condiciones lógicas.
# Por coerción implícita: TRUE se convierte en 1 y FALSE en 0.
# Al usar '+', las condiciones se transforman en enteros y la suma devuelve un integer.
# La 'L' indica que el resultado es de tipo integer (R usa double por defecto,
# pero cuando la operación es entre enteros, mantiene el tipo integer).
perfil_alto_riesgo <- ((edad > 45) + (isTRUE(fumador)) + (reclamaciones > 0)) >=2
perfil_alto_riesgo
## [1] TRUE
class(perfil_alto_riesgo)
## [1] "logical"
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
Una pregunta que puede surgir es, ¿por qué no hacemos…
prima_base * (1 + recargo) * (1 - descuento) ?
Revisemos el impacto del descuento sobre la prima base si hiciéramos eso.
prima_base = 0.02 * suma_asegurada
prima_final = prima_base * (1 + recargo) * (1 - descuento)
descuento_neto <- prima_base * (1 + recargo) - prima_final
# ¿Qué tan grande es el efecto del descuento respecto a la prima original?
descuento_neto / prima_base * 100
## [1] 3.3
En el esquema multiplicativo, el descuento se aplica sobre una prima ya incrementada por el recargo, generando así una tasa efectiva de descuento ligeramente mayor al 3%. Dado que tanto el recargo como el descuento deben aplicarse sobre la prima base, utilizamos un modelo lineal.
prima_base <- 0.02 * suma_asegurada
prima_final <- prima_base * (1 + recargo - descuento)
descuento_neto <- prima_base * (1 + recargo) - prima_final
descuento_neto / prima_base * 100
## [1] 3
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.
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, carácteres, 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"
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
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
¿Qué ocurre cuando aplicamos operadores entre vectores de distinta longitud?
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(), var(),
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
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
Si el vector contiene valores NA, debemos agregar un
argumento adicional para que la función los ignore en el cálculo.
salarios <- c(8000,9000,10000,15000, NA)
class(salarios)
## [1] "numeric"
mean(salarios)
## [1] NA
mean(salarios, 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"
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.
vector <- c(10,20,30,40,50)
# Recuperamos el 3er elemento del vector
elemento <- vector[3]
print(elemento)
## [1] 30
# Reasignamos valores por posición
vector[3] <- 33
print(vector)
## [1] 10 20 33 40 50
class(vector)
## [1] "numeric"
vector[3] <- "Hola"
class(vector)
## [1] "character"
print(vector)
## [1] "10" "20" "Hola" "40" "50"
salarios
## [1] 8000 9000 10000 15000 NA
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.
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.
salarios
## [1] 8000 9000 10000 15000
salarios > 10000
## [1] FALSE FALSE FALSE TRUE
salarios[salarios > 10000]
## [1] 15000
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.
Podemos 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
Otra 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
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
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"