DISTRIBUCIONES DE FRECUENCIAS

Taller_1

Autor/a
Afiliación

Lizeth Dahiana Caballero Bermeo

Fecha de publicación

25 de abril de 2025

Logo Universidad del Tolima

Ver código
# Verificar, instalar y activar el paquete "tidyverse"
if (!require(tidyverse)) {
  install.packages("tidyverse")
}
library(tidyverse)

# Verificar, instalar y activar el paquete "kableExtra"
if (!require(kableExtra)) {
  install.packages("kableExtra")
}
library(kableExtra)

# Verificar, instalar y activar el paquete "readxl"
if (!require(readxl)) {
  install.packages("readxl")
}
library(readxl)

1 . LEER EL DATASET

1.1 . EN FORMATO XLSX

Ver código
seguros <- read_excel("datos/seguros.xlsx")

1.2 . EN FORMATO CSV

Ver código
seguros_1 <- read.csv2("datos/seguros.csv")

2 . INTRODUCCION

Este trabajo se enfoca en el análisis de una base de datos proveniente del archivo seguros.xlsx, la cual reúne información relevante sobre características personales, condiciones de salud y ciertos hábitos de vida de un grupo de personas. El objetivo principal es explorar cómo estos factores pueden relacionarse con el costo de los seguros médicos.

Dentro de los datos disponibles se incluyen variables como el sexo, la edad, la región geográfica, el índice de masa corporal (IMC), el tabaquismo, el número de hijos, una valoración subjetiva y el precio del seguro. La mezcla de datos categóricos y numéricos permite realizar un análisis descriptivo con el que se pueden detectar tendencias, distribuciones y posibles asociaciones entre las variables.

Este análisis exploratorio constituye una base útil para comprender mejor qué aspectos podrían influir en el valor que una persona paga por su seguro médico, sentando las bases para estudios más profundos o modelos predictivos en etapas futuras.

3 . EXPORTAR DATASET

MOSTRAR

Ver código
head(seguros)
# A tibble: 6 × 8
   EDAD SEXO     IMC HIJOS FUMA  REGION    PRECIO CALIFICACION
  <dbl> <chr>  <dbl> <dbl> <chr> <chr>      <dbl> <chr>       
1    19 female  27.9     0 yes   southwest 16885. excellent   
2    18 male    33.8     1 no    southeast  1726. bad         
3    28 male    33       3 no    southeast  4449. bad         
4    33 male    22.7     0 no    northwest 21984. regular     
5    32 male    28.9     0 no    northwest  3867. regular     
6    31 female  25.7     0 no    southeast  3757. bad         

NOMBRE DE VARIABLE

Ver código
seguros %>% names
[1] "EDAD"         "SEXO"         "IMC"          "HIJOS"        "FUMA"        
[6] "REGION"       "PRECIO"       "CALIFICACION"

TIPOS DE VARIABLES

Ver código
glimpse(seguros)
Rows: 1,338
Columns: 8
$ EDAD         <dbl> 19, 18, 28, 33, 32, 31, 46, 37, 37, 60, 25, 62, 23, 56, 2…
$ SEXO         <chr> "female", "male", "male", "male", "male", "female", "fema…
$ IMC          <dbl> 27.900, 33.770, 33.000, 22.705, 28.880, 25.740, 33.440, 2…
$ HIJOS        <dbl> 0, 1, 3, 0, 0, 0, 1, 3, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, …
$ FUMA         <chr> "yes", "no", "no", "no", "no", "no", "no", "no", "no", "n…
$ REGION       <chr> "southwest", "southeast", "southeast", "northwest", "nort…
$ PRECIO       <dbl> 16884.924, 1725.552, 4449.462, 21984.471, 3866.855, 3756.…
$ CALIFICACION <chr> "excellent", "bad", "bad", "regular", "regular", "bad", "…

CANTIDAD DE VARIABLES

Ver código
seguros %>% names %>% length
[1] 8

TRANSFORMAR VARIABLES

Ver código
seguros <- seguros %>%
  mutate(
    SEXO = parse_factor(SEXO, levels = c("male", "female"), ordered = FALSE),
    FUMA = parse_factor(FUMA, levels = c("no", "yes"), ordered = TRUE),
    REGION = parse_factor(REGION, 
                          levels = c("northwest", "northeast", "southwest", "southeast"), 
                          ordered = FALSE),
    CALIFICACION = parse_factor(CALIFICACION, 
                                levels = c("bad", "regular", "good", "excellent"), 
                                ordered = TRUE)
  )

glimpse(seguros)
Rows: 1,338
Columns: 8
$ EDAD         <dbl> 19, 18, 28, 33, 32, 31, 46, 37, 37, 60, 25, 62, 23, 56, 2…
$ SEXO         <fct> female, male, male, male, male, female, female, female, m…
$ IMC          <dbl> 27.900, 33.770, 33.000, 22.705, 28.880, 25.740, 33.440, 2…
$ HIJOS        <dbl> 0, 1, 3, 0, 0, 0, 1, 3, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, …
$ FUMA         <ord> yes, no, no, no, no, no, no, no, no, no, no, yes, no, no,…
$ REGION       <fct> southwest, southeast, southeast, northwest, northwest, so…
$ PRECIO       <dbl> 16884.924, 1725.552, 4449.462, 21984.471, 3866.855, 3756.…
$ CALIFICACION <ord> excellent, bad, bad, regular, regular, bad, good, bad, go…

CLASES DE VARIABLES

Ver código
class(seguros$CALIFICACION)
[1] "ordered" "factor" 
Ver código
levels(seguros$CALIFICACION)
[1] "bad"       "regular"   "good"      "excellent"

4 . TABLAS DE FRECUENCIA

4.1 . VARIABLE CUALITATIVA NOMINAL

Ver código
# Instalar paquetes si es necesario
if (!require(readxl)) install.packages("readxl")
if (!require(dplyr)) install.packages("dplyr")
if (!require(kableExtra)) install.packages("kableExtra")

# Cargar librerías
library(readxl)
library(dplyr)
library(kableExtra)

# Leer archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable SEXO
tabla_nominal <- datos %>%
  count(SEXO) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%"),          # Porcentaje en texto
    FrecuenciaAcumulada = cumsum(n)                        # Frecuencia acumulada (opcional)
  )

# Mostrar tabla con formato elegante
tabla_nominal %>%
  select(SEXO, fi = n, hi, Porcentaje) %>%  # Selección y renombrado de columnas
  kable(caption = "Tabla de Frecuencia - Variable SEXO",
        col.names = c("Sexo", "fi", "hi", "Porcentaje"),
        align = c("l", "c", "c", "c")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, background = "#3892f8", color = "white")  # Color azul en encabezado
Tabla de Frecuencia - Variable SEXO
Sexo fi hi Porcentaje
female 662 0.4948 49.5%
male 676 0.5052 50.5%
Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(dplyr)) install.packages("dplyr")
if (!require(kableExtra)) install.packages("kableExtra")

library(readxl)
library(dplyr)
library(kableExtra)

# Leer el archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable FUMA
tabla_fuma <- datos %>%
  count(FUMA) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%"),           # Porcentaje
    FrecuenciaAcumulada = cumsum(n)                         # Frecuencia acumulada (opcional)
  )

# Mostrar tabla con formato elegante
tabla_fuma %>%
  select(FUMA, fi = n, hi, Porcentaje) %>%  # Selección y renombrado de columnas
  kable(caption = "Tabla de Frecuencia - Variable FUMA",
        col.names = c("Fuma", "fi", "hi", "Porcentaje"),
        align = c("l", "c", "c", "c")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, background = "#3892f8", color = "white")  # Encabezado azul y texto blanco
Tabla de Frecuencia - Variable FUMA
Fuma fi hi Porcentaje
no 1064 0.7952 79.5%
yes 274 0.2048 20.5%
Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(dplyr)) install.packages("dplyr")
if (!require(kableExtra)) install.packages("kableExtra")

library(readxl)
library(dplyr)
library(kableExtra)

# Leer el archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable REGION
tabla_region <- datos %>%
  count(REGION) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%"),           # Porcentaje
    FrecuenciaAcumulada = cumsum(n)                         # Frecuencia acumulada
  )

# Mostrar tabla con formato elegante
tabla_region %>%
  select(REGION, fi = n, hi, Porcentaje) %>%  # Selección y renombrado de columnas
  kable(caption = "Tabla de Frecuencia - Variable REGION",
        col.names = c("Región", "fi", "hi", "Porcentaje"),
        align = c("l", "c", "c", "c")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, background = "#3892f8", color = "white")  # Encabezado azul y texto blanco
Tabla de Frecuencia - Variable REGION
Región fi hi Porcentaje
northeast 324 0.2422 24.2%
northwest 325 0.2429 24.3%
southeast 364 0.2720 27.2%
southwest 325 0.2429 24.3%

DIAGRAMA DE BARRAS

Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")

library(readxl)
library(ggplot2)
library(dplyr)

# Leer los datos
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia
frecuencia_sexo <- datos %>%
  count(SEXO) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%")            # Porcentaje
  )

# Definir paleta personalizada de tonos de azul
colores_azules <- c("#3892f8", "#6fb9f4", "#a6d4fa", "#cce7ff")

# Crear diagrama de barras con porcentajes sobre las barras
ggplot(frecuencia_sexo, aes(x = SEXO, y = n, fill = SEXO)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Porcentaje), vjust = -0.5, size = 4.5) +  # Solo el porcentaje
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Diagrama de Barras - Variable SEXO",
    x = "Sexo",
    y = "Frecuencia"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 12),
    legend.position = "none"  # Oculta la leyenda si solo hay dos categorías
  )

Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")

library(readxl)
library(ggplot2)
library(dplyr)

# Leer los datos
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable SEXO
frecuencia_sexo <- datos %>%
  count(SEXO) %>%
  mutate(
    hi = round(n / sum(n), 4),
    Porcentaje = paste0(round(hi * 100, 1), "%"),
    ypos = cumsum(hi) - 0.5 * hi  # Posición para etiquetas
  )

# Definir paleta de colores azulados
colores_azules <- c("#3892f8", "#6fb9f4", "#a6d4fa", "#cce7ff")

# Crear gráfico circular
ggplot(frecuencia_sexo, aes(x = "", y = hi, fill = SEXO)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(y = ypos, label = Porcentaje), color = "white", size = 5) +  # Solo porcentaje
  scale_fill_manual(values = colores_azules) +
  labs(title = "Diagrama Circular - Variable SEXO", fill = "Sexo") +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.title = element_text(face = "bold")
  )

Interpretación: La distribución por sexo está equilibrada: 50.5% de los casos son hombres y 49.5% mujeres. Esta proporción casi simétrica sugiere una muestra equitativa en términos de género, lo cual es deseable para evitar sesgos en el análisis posterior. La frecuencia acumulada confirma esta paridad al alcanzar exactamente el 100% tras considerar ambas categorías.

Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")

library(readxl)
library(ggplot2)
library(dplyr)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable FUMA
frecuencia_fuma <- datos %>%
  count(FUMA) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%")            # Porcentaje
  )

# Definir paleta de azules personalizada
colores_azules <- c("#3892f8", "#6fb9f4", "#a6d4fa", "#cce7ff")

# Crear el gráfico de barras con porcentaje sobre las barras
ggplot(frecuencia_fuma, aes(x = FUMA, y = n, fill = FUMA)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Porcentaje), vjust = -0.5, size = 4.5) +  # Solo muestra el porcentaje
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Diagrama de Barras - Variable FUMA",
    x = "¿Fuma?",
    y = "Frecuencia"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 12),
    legend.position = "none"  # Oculta leyenda si no se necesita
  )

Ver código
# Crear tabla de frecuencia para la variable FUMA
frecuencia_fuma <- datos %>%
  count(FUMA) %>%
  arrange(desc(FUMA)) %>%  # Ordenar para que los colores y etiquetas coincidan
  mutate(
    hi = round(n / sum(n), 4),                          # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%"),       # Porcentaje como texto
    ymax = cumsum(hi),                                  # Límite superior del segmento
    ymin = c(0, head(ymax, n = -1)),                    # Límite inferior
    etiqueta = paste(FUMA, "-", Porcentaje)             # Texto combinado
  )

# Crear gráfico circular bien proporcionado
ggplot(frecuencia_fuma, aes(ymax = ymax, ymin = ymin, xmax = 1, xmin = 0, fill = FUMA)) +
  geom_rect(color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(x = 0.5, y = (ymin + ymax)/2, label = Porcentaje), color = "white", size = 5) +
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Diagrama Circular - Variable FUMA",
    fill = "¿Fuma?"
  ) +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.title = element_text(face = "bold"),
    legend.text = element_text(size = 10)
  )

Interpretación: El 79.5% de los individuos reportan no fumar, frente al 20.5% que sí lo hacen. Esta diferencia notable indica que la mayoría de la población analizada no fuma, lo cual puede influir en variables relacionadas con la salud. Esta proporción también es útil para comparar grupos y evaluar posibles asociaciones entre el hábito de fumar y otras características.

Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")

library(readxl)
library(ggplot2)
library(dplyr)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Crear tabla de frecuencia para la variable REGION
frecuencia_region <- datos %>%
  count(REGION) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%")            # Porcentaje
  )

# Definir paleta de tonos azules
colores_azules <- c("#3892f8", "#6fb9f4", "#a6d4fa", "#cce7ff")

# Crear gráfico de barras para REGION con porcentaje encima
ggplot(frecuencia_region, aes(x = REGION, y = n, fill = REGION)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Porcentaje), vjust = -0.5, size = 4.5) +  # Solo muestra porcentaje
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Diagrama de Barras - Variable REGION",
    x = "Región",
    y = "Frecuencia"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 12),
    legend.position = "none"
  )

Ver código
# Preparar datos para gráfico circular
frecuencia_region <- frecuencia_region %>%
  arrange(desc(REGION)) %>%  # Orden descendente para consistencia visual
  mutate(
    ymax = cumsum(hi),                       # Límite superior del segmento
    ymin = c(0, head(ymax, n = -1)),         # Límite inferior
    etiqueta = paste(REGION, "-", Porcentaje)  # Etiqueta completa
  )

# Crear gráfico circular con etiquetas bien posicionadas
ggplot(frecuencia_region, aes(ymax = ymax, ymin = ymin, xmax = 1, xmin = 0, fill = REGION)) +
  geom_rect(color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(x = 0.5, y = (ymin + ymax)/2, label = Porcentaje), color = "white", size = 5) +
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Diagrama Circular - Variable REGION",
    fill = "Región"
  ) +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.title = element_text(face = "bold"),
    legend.text = element_text(size = 10)
  )

Interpretación: Las cuatro regiones presentan una distribución relativamente uniforme: southeast (27.2%), southwest (24.3%), northwest (24.3%) y northeast (24.2%). Esta dispersión balanceada sugiere que no hay una sobre-representación geográfica en la muestra, lo cual es ideal para análisis comparativos entre regiones. La frecuencia acumulada muestra un incremento progresivo que refleja esta uniformidad.

4.2 . VARIABLE CUALITATIVA ORDINAL

Ver código
# Instalar y cargar paquetes necesarios
if (!require(readxl)) install.packages("readxl")
if (!require(dplyr)) install.packages("dplyr")
if (!require(kableExtra)) install.packages("kableExtra")

library(readxl)
library(dplyr)
library(kableExtra)

# Leer archivo Excel
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance")

# Asegurar orden correcto (usando los nombres en minúscula tal como están en el archivo)
datos$CALIFICACION <- factor(datos$CALIFICACION,
                             levels = c("bad", "regular", "good", "excellent"),
                             ordered = TRUE)

# Crear tabla de frecuencias ordenadas
tabla_ordinal <- datos %>%
  count(CALIFICACION) %>%
  mutate(
    hi = round(n / sum(n), 4),                             # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 1), "%"),          # Porcentaje
    FrecuenciaAcumulada = cumsum(n)                        # Frecuencia acumulada
  )

# Mostrar tabla con formato
tabla_ordinal %>%
  kable("html", col.names = c("calificacion", "(fi)", "(hi)", "Porcentaje", "Fi")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover")) %>%
  row_spec(0, background = "#3892f8", color = "white")
calificacion (fi) (hi) Porcentaje Fi
bad 343 0.2564 25.6% 343
regular 327 0.2444 24.4% 670
good 345 0.2578 25.8% 1015
excellent 323 0.2414 24.1% 1338

DIAGRAMA DE BARRAS

Ver código
# Instalar y cargar paquetes necesarios
if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")

library(ggplot2)
library(dplyr)

# Asegurar orden de la variable ordinal
datos$CALIFICACION <- factor(datos$CALIFICACION,
                             levels = c("bad", "regular", "good", "excellent"),
                             ordered = TRUE)

# Crear tabla de frecuencias con porcentajes
tabla_ordinal <- datos %>%
  count(CALIFICACION) %>%
  mutate(
    hi = round(n / sum(n), 4),
    Porcentaje = paste0(round(hi * 100, 1), "%")
  )

# Paleta de colores basada en #3892f8
colores_azules <- c("#a8ccf8", "#72b0f8", "#3892f8", "#1c6ed8")

# Gráfico de barras ordenado con porcentajes encima
ggplot(tabla_ordinal, aes(x = CALIFICACION, y = n, fill = CALIFICACION)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Porcentaje), vjust = -0.5, size = 4.5) +  # Solo muestra porcentaje
  scale_fill_manual(values = colores_azules) +
  labs(
    title = "Distribución de la variable Calificación",
    x = "Calificación",
    y = "Frecuencia"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    axis.title = element_text(face = "bold")
  )

Interpretación: La distribución de la variable ordinal CALIFICACION muestra una frecuencia bastante equilibrada entre sus cuatro niveles: bad (25.6%), regular (24.4%), good (25.8%) y excellent (24.1%). Esto indica una división casi simétrica entre calificaciones negativas y positivas. La frecuencia acumulada revela que el 50% de los casos tienen una calificación de regular o inferior, lo que permite identificar puntos de corte útiles para análisis posteriores. Esta tabla permite interpretar no solo cuántas personas están en cada categoría, sino también cómo se distribuyen a lo largo de una escala jerárquica de evaluación.

4.3 . VARIABLE CUANTITATIVA DISCRETA

Ver código
# Cargar librerías necesarias
library(readxl)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx")

# Usar la columna 'HIJOS' para crear la tabla de frecuencias
tabla_hijos <- table(datos$HIJOS)

# Mostrar la tabla de frecuencias
tabla_hijos

  0   1   2   3   4   5 
574 324 240 157  25  18 
Ver código
# Cargar librerías necesarias
library(readxl)
library(dplyr)
library(tibble)
library(knitr)
library(kableExtra)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx")

# Crear la tabla de frecuencia para la variable 'HIJOS'
tabla <- tibble(Hijos = datos$HIJOS) %>% 
  group_by(Hijos) %>% 
  summarise(fi = n()) %>%  # Calcular la frecuencia absoluta
  mutate(
    hi = round(fi / sum(fi), 4),  # Calcular la frecuencia relativa
    Porcentaje = paste0(hi * 100, "%"),  # Calcular el porcentaje
    Fi = cumsum(fi),  # Calcular la frecuencia acumulada
    Hi = cumsum(hi)   # Calcular la frecuencia acumulada relativa
  ) 

# Mostrar la tabla con color
tabla %>% 
  knitr::kable(
    col.names = c("Hijos", "$f_i$", "$h_i$", "Porcentaje", "$F_i$", "$H_i$"), 
    align = c("l", "r", "r", "r", "r", "r")  # Alinear las columnas
  ) %>% 
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),  # Opciones para estilizar la tabla
    full_width = FALSE,  # Tabla no ocupando el ancho completo
    position = "center"  # Centrar la tabla
  ) %>%
  # Agregar color al fondo de las celdas
  column_spec(1:ncol(tabla), background = "#3892f8", color = "white")  # Fondo azul con texto blanco
Hijos $f_i$ $h_i$ Porcentaje $F_i$ $H_i$
0 574 0.4290 42.9% 574 0.4290
1 324 0.2422 24.22% 898 0.6712
2 240 0.1794 17.94% 1138 0.8506
3 157 0.1173 11.73% 1295 0.9679
4 25 0.0187 1.87% 1320 0.9866
5 18 0.0135 1.35% 1338 1.0001

Variable cuantitativa discreta con totales

Ver código
# Cargar librerías necesarias
library(readxl)
library(dplyr)
library(tibble)
library(knitr)
library(kableExtra)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx")

# Crear la tabla de frecuencia para la variable 'HIJOS'
tabla <- tibble(Hijos = datos$HIJOS) %>% 
  group_by(Hijos) %>% 
  summarise(fi = n()) %>%  # Frecuencia absoluta
  mutate(
    hi = round(fi / sum(fi), 4),              # Frecuencia relativa
    Porcentaje = paste0(round(hi * 100, 2), "%"),  # Porcentaje con 2 decimales
    Fi = cumsum(fi),                          # Frecuencia acumulada
    Hi = cumsum(hi)                           # Frecuencia relativa acumulada
  )

# Crear la fila de totales antes de convertir columnas a texto
totales <- tibble(
  Hijos = "Total",
  fi = sum(tabla$fi),
  hi = round(sum(tabla$hi), 4),
  Porcentaje = paste0(round(sum(tabla$hi) * 100, 2), "%"),
  Fi = "",  # Dejar en blanco
  Hi = ""   # Dejar en blanco
)

# Convertir columnas a character
tabla <- tabla %>% mutate(
  Hijos = as.character(Hijos),
  Fi = as.character(Fi),
  Hi = as.character(Hi)
)

# Combinar con los totales
tabla_final <- bind_rows(tabla, totales)

# Mostrar la tabla final con estilo y encabezado en azul
tabla_final %>% 
  knitr::kable(
    col.names = c("Hijos", "$f_i$", "$h_i$", "Porcentaje", "$F_i$", "$H_i$"), 
    align = c("l", "r", "r", "r", "r", "r"),
    escape = FALSE
  ) %>% 
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = FALSE,
    position = "center"
  ) %>%
  row_spec(0, background = "#3892f8", color = "white")  # Solo encabezado azul
Hijos $f_i$ $h_i$ Porcentaje $F_i$ $H_i$
0 574 0.4290 42.9% 574 0.429
1 324 0.2422 24.22% 898 0.6712
2 240 0.1794 17.94% 1138 0.8506
3 157 0.1173 11.73% 1295 0.9679
4 25 0.0187 1.87% 1320 0.9866
5 18 0.0135 1.35% 1338 1.0001
Total 1338 1.0001 100.01%

DIAGRAMA DE BARRAS

Ver código
# Cargar librerías necesarias
library(ggplot2)
library(readxl)
library(dplyr)

# Leer los datos desde el archivo Excel
datos <- read_excel("datos/seguros.xlsx")

# Calcular las frecuencias y los porcentajes
tabla_hijos <- datos %>%
  group_by(HIJOS) %>%
  summarise(fi = n()) %>%
  mutate(
    porcentaje = fi / sum(fi) * 100  # Calcular el porcentaje
  )

# Crear un diagrama de bastones (linerange)
ggplot(data = tabla_hijos, aes(x = factor(HIJOS), y = fi)) +
  geom_linerange(aes(ymin = 0, ymax = fi), color = "#3892f8", size = 1.5) +  # Bastones
  geom_point(size = 3, color = "#1f4e79") +  # Punto en la cima del bastón
  geom_text(aes(label = paste0(round(porcentaje, 1), "%")), vjust = -1, color = "black") +  # Porcentaje encima del punto
  labs(
    title = "Diagrama de Bastones de la Variable Hijos",
    x = "Número de Hijos",
    y = "Frecuencia"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5),  # Centrar el título
    axis.text.x = element_text(angle = 45, hjust = 1)  # Rotar etiquetas del eje X
  )

Interpretación: El análisis de la variable Número de Hijos muestra que la mayoría de la población tiene entre 1 y 2 hijos. El porcentaje más alto se observa en los individuos con 2 hijos, seguido por aquellos con 1 hijo. Las familias con más de 3 hijos son menos frecuentes, lo que indica que los tamaños familiares pequeños predominan en esta muestra.

4.4 . VARIABLE CUANTITATIVA CONTINUA

4.4.1 . IMC

Ver código
set.seed(555)
imc <- round(rnorm(1338, mean = 28, sd = 6), 1)
min(imc)
[1] 9.2
Ver código
max(imc)
[1] 48.5
Ver código
diff(range(imc))
[1] 39.3
Ver código
1+log2(1338)
[1] 11.38586
Ver código
1+3.322*log10(1338)
[1] 11.38609
Ver código
39.3/12
[1] 3.275
Ver código
3.3*12
[1] 39.6
Ver código
39.6-39.3
[1] 0.3
Ver código
#NUEVO MINIMO MIN(imc)
(9.2)-0.3/2 
[1] 9.05
Ver código
#NUEVO MAXIMO MAX(imc)
(48.5)+0.3/2
[1] 48.65
  • Número de intervalos: 12

  • Nuevo mínimo: 9.05

  • Nuevo máximo: 48.65

TABLA DE VARIABLE CUANTITATIVA CONTINUA IMC

Ver código
library(dplyr)
library(knitr)
library(kableExtra)

# Crear los intervalos
interv <- cut(x = imc, breaks = seq(9.05, 48.65, by = 3.3), include.lowest = TRUE)

# Tabla de frecuencias
tibble(imc = interv) %>% 
  group_by(imc) %>%  
  summarise(fi = n()) %>% 
  mutate(
    # Calcular el punto medio automáticamente
    mi = (as.numeric(sub("\\((.+),.*", "\\1", imc)) + 
          as.numeric(sub("[^,]*,([^]]*)\\]", "\\1", imc))) / 2
  ) %>% 
  relocate(imc, mi, fi) %>% 
  mutate(
    hi = fi / sum(fi),       # Frecuencia relativa
    Fi = cumsum(fi),         # Frecuencia acumulada
    Hi = cumsum(hi)          # Frecuencia relativa acumulada
  ) %>% 
  knitr::kable(
    col.names = c("IMC", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c"),
    digits = 4
  ) %>% 
  kableExtra::kable_styling(full_width = FALSE) %>% 
  kableExtra::add_header_above(c("Distribuciones de frecuencias para la variable IMC" = 6)) %>% 
  kableExtra::kable_styling(
    bootstrap_options = c("striped", "hover"),
    position = "center",
    font_size = 14
  ) %>% 
  kableExtra::column_spec(1, bold = TRUE, color = "white", background = "#3892f8")
Distribuciones de frecuencias para la variable IMC
IMC mi fi hi Fi Hi
[9.05,12.4] NA 8 0.0060 8 0.0060
(12.4,15.6] 14.00 18 0.0135 26 0.0194
(15.6,18.9] 17.25 64 0.0478 90 0.0673
(18.9,22.2] 20.55 135 0.1009 225 0.1682
(22.2,25.6] 23.90 225 0.1682 450 0.3363
(25.6,28.8] 27.20 292 0.2182 742 0.5546
(28.8,32.1] 30.45 285 0.2130 1027 0.7676
(32.1,35.5] 33.80 180 0.1345 1207 0.9021
(35.5,38.8] 37.15 87 0.0650 1294 0.9671
(38.8,42] 40.40 30 0.0224 1324 0.9895
(42,45.3] 43.65 10 0.0075 1334 0.9970
(45.3,48.6] 46.95 4 0.0030 1338 1.0000

TABLA DE TOTALES DE VARIABLE CUANTITATIVA CONTINUA IMC

Ver código
library(dplyr)
library(knitr)
library(kableExtra)

# Crear los intervalos
interv <- cut(x = imc, breaks = seq(9.05, 48.65, by = 3.3), include.lowest = TRUE)

# Construir la tabla de frecuencias
tabla_imc <- tibble(imc = interv) %>% 
  group_by(imc) %>%  
  summarise(fi = n()) %>% 
  mutate(
    # Calcular punto medio automáticamente desde los intervalos
    mi = (as.numeric(sub("\\((.+),.*", "\\1", imc)) + 
          as.numeric(sub("[^,]*,([^]]*)\\]", "\\1", imc))) / 2
  ) %>% 
  relocate(imc, mi, fi) %>% 
  mutate(
    hi = fi / sum(fi),
    Fi = cumsum(fi),
    Hi = cumsum(hi)
  )

# Agregar fila de totales
totales <- tibble(
  imc = "Total",
  mi = NA,
  fi = sum(tabla_imc$fi),
  hi = sum(tabla_imc$hi),
  Fi = NA,
  Hi = NA
)

# Unir tabla con fila de totales
tabla_final <- bind_rows(tabla_imc, totales)

# Mostrar tabla con formato
tabla_final %>% 
  knitr::kable(
    col.names = c("IMC", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c"),
    digits = 4
  ) %>% 
  kableExtra::kable_styling(full_width = FALSE) %>% 
  kableExtra::add_header_above(c("Distribuciones de frecuencias para la variable IMC" = 6)) %>% 
  kableExtra::kable_styling(
    bootstrap_options = c("striped", "hover"),
    position = "center",
    font_size = 14
  ) %>% 
  kableExtra::column_spec(1, bold = TRUE, color = "white", background = "#3892f8")
Distribuciones de frecuencias para la variable IMC
IMC mi fi hi Fi Hi
[9.05,12.4] NA 8 0.0060 8 0.0060
(12.4,15.6] 14.00 18 0.0135 26 0.0194
(15.6,18.9] 17.25 64 0.0478 90 0.0673
(18.9,22.2] 20.55 135 0.1009 225 0.1682
(22.2,25.6] 23.90 225 0.1682 450 0.3363
(25.6,28.8] 27.20 292 0.2182 742 0.5546
(28.8,32.1] 30.45 285 0.2130 1027 0.7676
(32.1,35.5] 33.80 180 0.1345 1207 0.9021
(35.5,38.8] 37.15 87 0.0650 1294 0.9671
(38.8,42] 40.40 30 0.0224 1324 0.9895
(42,45.3] 43.65 10 0.0075 1334 0.9970
(45.3,48.6] 46.95 4 0.0030 1338 1.0000
Total NA 1338 1.0000 NA NA

HISTOGRAMA

Ver código
library(ggplot2)

# Asegurarse de que los factores estén en el orden correcto
tabla_plot <- tabla_imc
tabla_plot$imc <- factor(tabla_plot$imc, levels = tabla_plot$imc)

# Crear el histograma horizontal (barras horizontales)
ggplot(tabla_plot, aes(x = imc, y = fi)) +
  geom_bar(stat = "identity", fill = "#3892f8") +
  coord_flip() +
  labs(
    title = "Histograma Sagital de Frecuencia Absoluta (IMC)",
    x = "Intervalos de IMC",
    y = "Frecuencia absoluta (fi)"
  ) +
  theme_minimal(base_size = 14)

INTERPRETACIÓN: El intervalo de IMC más frecuente en la población es de 21.65 a 24.95, con 25 personas, lo que indica que la mayoría se encuentra en un rango considerado como peso normal. Le sigue el intervalo de 24.95 a 28.25, con 18 personas, correspondiente al rango de sobrepeso.

En total, alrededor del 70% de la muestra se concentra entre los IMC de 18.35 y 28.25, lo que sugiere que la mayoría de la población presenta un estado nutricional entre normal y sobrepeso. Los intervalos extremos (menor a 18.5 o mayor a 30) tienen frecuencias mucho más bajas, lo que indica que hay poca presencia de desnutrición o de obesidad severa.

Esta distribución sugiere una población relativamente saludable, aunque con una proporción significativa en riesgo de desarrollar sobrepeso si no se implementan medidas preventivas.

4.4.2 . EDAD

Ver código
min(datos$EDAD)
[1] 18
Ver código
max(datos$EDAD)
[1] 64
Ver código
diff(range(datos$EDAD))
[1] 46
Ver código
1+log2(1338)
[1] 11.38586
Ver código
1+3.322*log10(1338)
[1] 11.38609
Ver código
46/12
[1] 3.833333
Ver código
3.8*12
[1] 45.6
Ver código
46-45.6
[1] 0.4
Ver código
#NUEVO MINIMO MIN(edad)
(18)-0.4/2
[1] 17.8
Ver código
#NUEVO MAXIMO MAX(edad)
(64)+0.4/2
[1] 64.2
  • Número de intervalos: 12

  • Nuevo mínimo: 17.8

  • Nuevo máximo: 64.2

TABLA DE VARIABLE CUANTITATIVA CONTINUA EDAD

Ver código
library(dplyr)
library(knitr)
library(kableExtra)

# Cortar la variable edad en intervalos de amplitud 3.8
interv <- cut(x = datos$EDAD, breaks = seq(17.8, 64.2, by = 3.8), include.lowest = TRUE)

tibble(edad = interv) %>% 
  group_by(edad) %>%  
  summarise(fi = n()) %>% 
  mutate(
    # Calcular punto medio automáticamente
    mi = (as.numeric(sub("\\((.+),.*", "\\1", edad)) + 
          as.numeric(sub("[^,]*,([^]]*)\\]", "\\1", edad))) / 2
  ) %>% 
  relocate(edad, mi, fi) %>% 
  mutate(
    hi = fi / sum(fi),       # Frecuencia relativa
    Fi = cumsum(fi),         # Frecuencia acumulada
    Hi = cumsum(hi)          # Frecuencia relativa acumulada
  ) %>% 
  knitr::kable(
    col.names = c("EDAD", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c")
  ) %>% 
  kableExtra::kable_styling(full_width = FALSE) %>% 
  kableExtra::add_header_above(c("Distribuciones de frecuencias para la variable EDAD" = 6)) %>% 
  kableExtra::kable_styling(
    bootstrap_options = c("striped", "hover"),
    position = "center",
    font_size = 14
  ) %>% 
  kableExtra::column_spec(1, bold = TRUE, color = "white", background = "#3892f8")
Distribuciones de frecuencias para la variable EDAD
EDAD mi fi hi Fi Hi
[17.8,21.6] NA 194 0.1449925 194 0.1449925
(21.6,25.4] 23.5 112 0.0837070 306 0.2286996
(25.4,29.2] 27.3 111 0.0829596 417 0.3116592
(29.2,33] 31.1 106 0.0792227 523 0.3908819
(33,36.8] 34.9 76 0.0568012 599 0.4476831
(36.8,40.6] 38.7 102 0.0762332 701 0.5239163
(40.6,44.4] 42.5 108 0.0807175 809 0.6046338
(44.4,48.2] 46.3 116 0.0866966 925 0.6913303
(48.2,52] 50.1 115 0.0859492 1040 0.7772795
(52,55.8] 53.9 82 0.0612855 1122 0.8385650
(55.8,59.6] 57.7 102 0.0762332 1224 0.9147982
(59.6,63.4] 61.5 92 0.0687593 1316 0.9835575
NA NA 22 0.0164425 1338 1.0000000

TABLA DE TOTALES DE VARIABLE CUANTITATIVA CONTINUA EDAD

Ver código
library(dplyr)
library(knitr)
library(kableExtra)

# Cortar la variable edad en intervalos
interv <- cut(x = datos$EDAD, breaks = seq(17.8, 64.2, by = 3.8), include.lowest = TRUE)

# Tabla con totales
tabla <- tibble(edad = interv) %>% 
  group_by(edad) %>%  
  summarise(fi = n()) %>% 
  mutate(
    mi = (as.numeric(sub("\\((.+),.*", "\\1", edad)) + 
          as.numeric(sub("[^,]*,([^]]*)\\]", "\\1", edad))) / 2
  ) %>% 
  relocate(edad, mi, fi) %>% 
  mutate(
    hi = fi / sum(fi),
    Fi = cumsum(fi),
    Hi = cumsum(hi)
  )

# Crear fila de totales
totales <- tibble(
  edad = "Total",
  mi = NA,
  fi = sum(tabla$fi),
  hi = sum(tabla$hi),
  Fi = NA,
  Hi = NA
)

# Unir tabla con totales
tabla_final <- bind_rows(tabla, totales)

# Mostrar tabla
tabla_final %>% 
  knitr::kable(
    col.names = c("EDAD", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c"),
    digits = 4
  ) %>% 
  kableExtra::kable_styling(full_width = FALSE) %>% 
  kableExtra::add_header_above(c("Distribuciones de frecuencias para la variable EDAD" = 6)) %>% 
  kableExtra::kable_styling(
    bootstrap_options = c("striped", "hover"),
    position = "center",
    font_size = 14
  ) %>% 
  kableExtra::column_spec(1, bold = TRUE, color = "white", background = "#3892f8")
Distribuciones de frecuencias para la variable EDAD
EDAD mi fi hi Fi Hi
[17.8,21.6] NA 194 0.1450 194 0.1450
(21.6,25.4] 23.5 112 0.0837 306 0.2287
(25.4,29.2] 27.3 111 0.0830 417 0.3117
(29.2,33] 31.1 106 0.0792 523 0.3909
(33,36.8] 34.9 76 0.0568 599 0.4477
(36.8,40.6] 38.7 102 0.0762 701 0.5239
(40.6,44.4] 42.5 108 0.0807 809 0.6046
(44.4,48.2] 46.3 116 0.0867 925 0.6913
(48.2,52] 50.1 115 0.0859 1040 0.7773
(52,55.8] 53.9 82 0.0613 1122 0.8386
(55.8,59.6] 57.7 102 0.0762 1224 0.9148
(59.6,63.4] 61.5 92 0.0688 1316 0.9836
NA NA 22 0.0164 1338 1.0000
Total NA 1338 1.0000 NA NA

HISTOGRAMA

Ver código
library(ggplot2)

# Asegúrate de que tienes el vector edad
# Por ejemplo: edad <- c(....)  # tu vector numérico con los datos

# Crear el histograma con densidad
ggplot(data.frame(edad = datos$EDAD), aes(x = edad)) +
  geom_histogram(aes(y = ..density..), 
                 binwidth = 3.8, 
                 fill = "#3892f8", 
                 color = "black") +
  geom_density(color = "black", size = 1) +
  labs(
    title = "Histograma de Densidad - Edad",
    x = "Edad",
    y = "Densidad"
  ) +
  theme_minimal(base_size = 14)

INTERPRETACIÓN: El histograma muestra una distribución normal de la edad, con una mayor concentración de personas entre los 30 y 45 años. La forma simétrica indica que la mayoría de los datos se agrupan en torno a la media, sin presencia notable de valores extremos. Esto sugiere una población equilibrada en términos etarios, predominantemente en etapa adulta media.

4.4.3 . PRECIO

Ver código
min(datos$PRECIO)
[1] 1121.874
Ver código
max(datos$PRECIO)
[1] 63770.43
Ver código
diff(range(datos$PRECIO))
[1] 62648.55
Ver código
1+log2(1338)
[1] 11.38586
Ver código
1+3.322*log10(1338)
[1] 11.38609
Ver código
62648.55/12
[1] 5220.713
Ver código
5220.8*12
[1] 62649.6
Ver código
62649.6-62648.55
[1] 1.05
Ver código
#NUEVO MINIMO MIN(PRECIO)
( 1121.874)-1.05/2
[1] 1121.349
Ver código
#NUEVO MAXIMO MAX(precio)
(63770.43)+1.05/2
[1] 63770.96
  • Número de intervalos: 12

  • Nuevo mínimo: 1121.349

  • Nuevo máximo: 63770.96

TABLA DE VARIABLE CUANTITATIVA CONTINUA PRECIO

Ver código
library(dplyr)
library(readxl)
library(knitr)
library(kableExtra)

# Leer datos desde Excel (corregido)
datos <- read_excel("datos/seguros.xlsx")

# Crear intervalos personalizados de PRECIO
interv <- cut(
  x = datos$PRECIO,
  breaks = seq(1121.349, 63770.96, by = 5220.8),
  include.lowest = TRUE
)

# Crear tabla de frecuencia
tibble(PRECIO = interv) %>%
  group_by(PRECIO) %>%
  summarise(fi = n(), .groups = "drop") %>%
  mutate(
    # Punto medio calculado manualmente desde el primer valor
    mi = seq(3731.75, 61181.55, by = 5220.8)
  ) %>%
  relocate(PRECIO, mi, fi) %>%
  mutate(
    hi = fi / sum(fi),      # Frecuencia relativa
    Fi = cumsum(fi),        # Frecuencia acumulada
    Hi = cumsum(hi)         # Frecuencia relativa acumulada
  ) %>%
  knitr::kable(
    col.names = c("PRECIO", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c")
  ) %>%
  kable_styling(full_width = FALSE) %>%
  add_header_above(c("Distribuciones de frecuencias para la variable PRECIO" = 6)) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), font_size = 14) %>%
  column_spec(1, bold = TRUE, color = "white", background = "#3892f8")
Distribuciones de frecuencias para la variable PRECIO
PRECIO mi fi hi Fi Hi
[1.12e+03,6.34e+03] 3731.75 453 0.3385650 453 0.3385650
(6.34e+03,1.16e+04] 8952.55 362 0.2705531 815 0.6091181
(1.16e+04,1.68e+04] 14173.35 190 0.1420030 1005 0.7511211
(1.68e+04,2.2e+04] 19394.15 94 0.0702541 1099 0.8213752
(2.2e+04,2.72e+04] 24614.95 58 0.0433483 1157 0.8647235
(2.72e+04,3.24e+04] 29835.75 27 0.0201794 1184 0.8849028
(3.24e+04,3.77e+04] 35056.55 48 0.0358744 1232 0.9207773
(3.77e+04,4.29e+04] 40277.35 52 0.0388640 1284 0.9596413
(4.29e+04,4.81e+04] 45498.15 38 0.0284006 1322 0.9880419
(4.81e+04,5.33e+04] 50718.95 11 0.0082212 1333 0.9962631
(5.33e+04,5.86e+04] 55939.75 1 0.0007474 1334 0.9970105
(5.86e+04,6.38e+04] 61160.55 4 0.0029895 1338 1.0000000

TABLA DE TOTALES DE VARIABLE CUANTITATIVA CONTINUA PRECIO

Ver código
library(dplyr)
library(readxl)
library(knitr)
library(kableExtra)

# Leer datos desde Excel
datos <- read_excel("datos/seguros.xlsx")

# Crear intervalos personalizados de PRECIO
interv <- cut(
  x = datos$PRECIO,
  breaks = seq(1121.349, 63770.96, by = 5220.8),
  include.lowest = TRUE
)

# Tabla principal con frecuencia y demás columnas
tabla <- tibble(PRECIO = interv) %>%
  group_by(PRECIO) %>%
  summarise(fi = n(), .groups = "drop") %>%
  mutate(
    mi = seq(3731.75, 61181.55, by = 5220.8)
  ) %>%
  relocate(PRECIO, mi, fi) %>%
  mutate(
    hi = fi / sum(fi),
    Fi = cumsum(fi),
    Hi = cumsum(hi)
  )

# Crear fila de totales
totales <- tibble(
  PRECIO = "Total",
  mi = NA,
  fi = sum(tabla$fi),
  hi = sum(tabla$hi),
  Fi = max(tabla$Fi),
  Hi = max(tabla$Hi)
)

# Unir tabla y totales
tabla_final <- bind_rows(tabla, totales)

# Mostrar tabla con totales
tabla_final %>%
  knitr::kable(
    col.names = c("PRECIO", "mi", "fi", "hi", "Fi", "Hi"),
    align = c("c", "c", "c", "c", "c", "c"),
    format.args = list(big.mark = ",", digits = 4)
  ) %>%
  kable_styling(full_width = FALSE) %>%
  add_header_above(c("Distribuciones de frecuencias para la variable PRECIO" = 6)) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), font_size = 14) %>%
  column_spec(1, bold = TRUE, color = "white", background = "#3892f8") %>%
  row_spec(nrow(tabla_final), bold = TRUE, color = "black", background = "#D3D3D3")
Distribuciones de frecuencias para la variable PRECIO
PRECIO mi fi hi Fi Hi
[1.12e+03,6.34e+03] 3,732 453 0.3385650 453 0.3386
(6.34e+03,1.16e+04] 8,953 362 0.2705531 815 0.6091
(1.16e+04,1.68e+04] 14,173 190 0.1420030 1,005 0.7511
(1.68e+04,2.2e+04] 19,394 94 0.0702541 1,099 0.8214
(2.2e+04,2.72e+04] 24,615 58 0.0433483 1,157 0.8647
(2.72e+04,3.24e+04] 29,836 27 0.0201794 1,184 0.8849
(3.24e+04,3.77e+04] 35,057 48 0.0358744 1,232 0.9208
(3.77e+04,4.29e+04] 40,277 52 0.0388640 1,284 0.9596
(4.29e+04,4.81e+04] 45,498 38 0.0284006 1,322 0.9880
(4.81e+04,5.33e+04] 50,719 11 0.0082212 1,333 0.9963
(5.33e+04,5.86e+04] 55,940 1 0.0007474 1,334 0.9970
(5.86e+04,6.38e+04] 61,161 4 0.0029895 1,338 1.0000
Total NA 1,338 1.0000000 1,338 1.0000

HISTOGRAMA

Ver código
library(dplyr)
library(readxl)
library(ggplot2)

# Leer datos
datos <- read_excel("datos/seguros.xlsx")

# Crear intervalos
breaks <- seq(1121.349, 63770.96, by = 5220.8)
interv <- cut(datos$PRECIO, breaks = breaks, include.lowest = TRUE)

# Crear tabla con densidad y punto medio
tabla <- tibble(PRECIO = interv) %>%
  group_by(PRECIO) %>%
  summarise(fi = n(), .groups = "drop") %>%
  mutate(
    amplitud = 5220.8,
    n = sum(fi),
    densidad = fi / (n * amplitud),
    mi = seq(3731.75, 61181.55, by = 5220.8)  # puntos medios
  )

# Histograma de densidad con curva suavizada
ggplot() +
  # Barras del histograma
  geom_col(
    data = tabla,
    aes(x = mi, y = densidad),
    fill = "#3892f8",
    color = "black",
    width = 5220.8
  ) +
  # Curva de densidad
  geom_density(
    data = datos,
    aes(x = PRECIO, y = ..density..),
    color = "#fb8500",
    size = 1.2
  ) +
  labs(
    title = "Histograma de Densidad con Curva Suavizada (PRECIO)",
    x = "PRECIO",
    y = "Densidad"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

INTERPRETACIÓN: La variable PRECIO presenta una distribución asimétrica positiva (sesgada a la derecha), evidenciada tanto en el histograma de densidad como en la curva suavizada. Esto indica que la mayoría de los seguros tienen precios ubicados en los intervalos más bajos, mientras que hay menos casos en los niveles de precio más altos, aunque estos últimos presentan una alta variabilidad.

El punto medio de mayor frecuencia se sitúa aproximadamente entre 3,700 y 8,900 unidades monetarias, lo que sugiere que ese es el rango más común de precios de seguros en la muestra. La disminución progresiva en la frecuencia conforme aumenta el precio sugiere que los seguros de alto costo son menos frecuentes pero aún significativos.

El análisis de densidad revela que, aunque existe una concentración clara de precios bajos, no se descarta la presencia de valores atípicos en los extremos superiores, lo cual puede tener implicaciones importantes para estrategias de segmentación o diseño de productos financieros ajustados al perfil económico de los clientes.

5 . CONCLUSIÓN

El análisis exploratorio realizado sobre la base de datos de seguros médicos permitió comprender las características principales de la población estudiada y extraer los datos directamente del documento de seguros médicos, asegurando su relevancia para la industria. Mediante un enfoque univariado se describieron con detalle las variables cualitativas nominales (SEXO, FUMA, REGIÓN), ordinales (CALIFICACIÓN) y discretas (NÚMERO DE HIJOS). En SEXO se observó una distribución casi equitativa entre hombres (50.5 %) y mujeres (49.5 %); en FUMA, un 79.5 % de no fumadores frente a un 20.5 % de fumadores; y en REGIÓN la muestra resultó homogénea entre zonas geográficas. La variable ordinal CALIFICACIÓN mostró una división casi simétrica entre sus cuatro niveles (bad: 25.6 %, regular: 24.4 %, good: 25.8 %, excellent: 24.1 %), mientras que el recuento de hijos reveló que la mayoría de los asegurados tiene entre 0 y 2 hijos, con muy baja frecuencia de familias numerosas.

En cuanto a las variables cuantitativas continuas, el IMC se concentró mayoritariamente en los rangos de peso normal y sobrepeso (entre 18.35 y 28.25 kg/m²), con poca presencia de desnutrición u obesidad severa. La edad sigue una distribución aproximada a la normal, centrada entre los 30 y 45 años, y el precio del seguro presenta un sesgo positivo, con la mayoría de pólizas en rangos de costo bajo–medio y una cola larga de seguros de alto precio. Además, la variable “precio del seguro” mostró una tendencia al alza en asegurados fumadores y con IMC elevado, lo que indica un posible esquema de tarificación basado en el riesgo sanitario.

La combinación de tablas de frecuencia, diagramas de barras, histogramas y análisis de densidad proporciona una base sólida para avanzar hacia análisis bivariados o modelos predictivos (por ejemplo, regresiones de costo), así como para diseñar estrategias de segmentación de mercado y políticas de tarificación más justas y precisas, adaptadas al perfil de riesgo de cada grupo de asegurados.

Ver código
#–– Paquetes necesarios ––#
if(!require(readxl))    install.packages("readxl")
if(!require(dplyr))     install.packages("dplyr")
if(!require(ggplot2))   install.packages("ggplot2")
if(!require(patchwork)) install.packages("patchwork")

library(readxl)
library(dplyr)
library(ggplot2)
library(patchwork)

#–– Cargar datos y preparar variables ––#
datos <- read_excel("datos/seguros.xlsx", sheet = "insurance") %>%
  mutate(
    SEXO          = factor(SEXO, levels = c("male","female")),
    FUMA          = factor(FUMA, levels = c("no","yes")),
    REGION        = factor(REGION),
    CALIFICACION  = factor(CALIFICACION,
                           levels = c("bad","regular","good","excellent"),
                           ordered = TRUE),
    HIJOS         = factor(HIJOS),
    EDAD          = as.numeric(EDAD),
    IMC           = as.numeric(IMC),
    PRECIO        = as.numeric(PRECIO)
  )

#–– Diagramas de barras ––#
p_sexo <- ggplot(datos, aes(x = SEXO, fill = SEXO)) +
  geom_bar() +
  labs(title="SEXO") +
  theme_minimal() +
  theme(legend.position="none")

p_fuma <- ggplot(datos, aes(x = FUMA, fill = FUMA)) +
  geom_bar() +
  labs(title="FUMA") +
  theme_minimal() +
  theme(legend.position="none")

p_region <- ggplot(datos, aes(x = REGION, fill = REGION)) +
  geom_bar() +
  labs(title="REGIÓN") +
  theme_minimal() +
  theme(legend.position="none")

p_calif <- ggplot(datos, aes(x = CALIFICACION, fill = CALIFICACION)) +
  geom_bar() +
  labs(title="CALIFICACIÓN (ordinal)") +
  theme_minimal() +
  theme(legend.position="none")

#–– Diagrama de bastones para HIJOS ––#
p_hijos <- datos %>%
  count(HIJOS) %>%
  mutate(porcentaje = n / sum(n) * 100) %>%
  ggplot(aes(x = HIJOS, y = n)) +
  geom_linerange(aes(ymin = 0, ymax = n), color = "#3892f8", size = 1.5) +
  geom_point(size = 3, color = "#1f4e79") +
  geom_text(aes(label = paste0(round(porcentaje, 1), "%")), vjust = -1, color = "black") +
  labs(title = "NÚMERO DE HIJOS (discreto)", x = "Hijos", y = "Frecuencia") +
  theme_minimal() +
  theme(legend.position = "none")

#–– Histogramas con densidad usando after_stat() ––#
p_imc <- ggplot(datos, aes(x = IMC)) +
  geom_histogram(aes(y = after_stat(density)),
                 binwidth = 3.3,
                 fill = "#3892f8",
                 color = "white") +
  geom_density(color = "black", size = 0.8) +
  labs(title="IMC", x="IMC (kg/m²)", y="Densidad") +
  theme_minimal()

p_edad <- ggplot(datos, aes(x = EDAD)) +
  geom_histogram(aes(y = after_stat(density)),
                 binwidth = 3.8,
                 fill = "#3892f8",
                 color = "white") +
  geom_density(color = "black", size = 0.8) +
  labs(title="EDAD", x="Edad (años)", y="Densidad") +
  theme_minimal()

p_precio <- ggplot(datos, aes(x = PRECIO)) +
  geom_histogram(aes(y = after_stat(density)),
                 binwidth = 5220.8,
                 fill = "#3892f8",
                 color = "white") +
  geom_density(aes(x = PRECIO),
               color = "#fb8500",
               size = 0.8) +
  labs(title="PRECIO", x="Precio del seguro", y="Densidad") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle=45, hjust=1))

#–– Combinar todo con patchwork ––#
(p_sexo + p_fuma + p_region + p_calif) /
(p_hijos + p_imc + p_edad + p_precio) +
  plot_annotation(
    title    = "Distribuciones de Variables — Base de Seguros Médicos",
    subtitle = "Datos extraídos del documento de seguros médicos",
    theme    = theme(
      plot.title    = element_text(face="bold", size=16),
      plot.subtitle = element_text(size=12)
    )
  )

6 . BIBLIOGRAFIA

Ver código
# Lista de paquetes usados
paquetes_usados <- c("readxl", "dplyr", "ggplot2", "patchwork")

# Mostrar la cita para cada paquete
for (pkg in paquetes_usados) {
  cat("\n---", pkg, "---\n")
  print(citation(pkg))
}

--- readxl ---
To cite package 'readxl' in publications use:

  Wickham H, Bryan J (2025). _readxl: Read Excel Files_. R package
  version 1.4.5, https://github.com/tidyverse/readxl,
  <https://readxl.tidyverse.org>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {readxl: Read Excel Files},
    author = {Hadley Wickham and Jennifer Bryan},
    year = {2025},
    note = {R package version 1.4.5, https://github.com/tidyverse/readxl},
    url = {https://readxl.tidyverse.org},
  }

--- dplyr ---
To cite package 'dplyr' in publications use:

  Wickham H, François R, Henry L, Müller K, Vaughan D (2023). _dplyr: A
  Grammar of Data Manipulation_. R package version 1.1.4,
  https://github.com/tidyverse/dplyr, <https://dplyr.tidyverse.org>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {dplyr: A Grammar of Data Manipulation},
    author = {Hadley Wickham and Romain François and Lionel Henry and Kirill Müller and Davis Vaughan},
    year = {2023},
    note = {R package version 1.1.4, https://github.com/tidyverse/dplyr},
    url = {https://dplyr.tidyverse.org},
  }

--- ggplot2 ---
To cite ggplot2 in publications, please use

  H. Wickham. ggplot2: Elegant Graphics for Data Analysis.
  Springer-Verlag New York, 2016.

A BibTeX entry for LaTeX users is

  @Book{,
    author = {Hadley Wickham},
    title = {ggplot2: Elegant Graphics for Data Analysis},
    publisher = {Springer-Verlag New York},
    year = {2016},
    isbn = {978-3-319-24277-4},
    url = {https://ggplot2.tidyverse.org},
  }

--- patchwork ---
To cite package 'patchwork' in publications use:

  Pedersen T (2024). _patchwork: The Composer of Plots_. R package
  version 1.3.0, https://github.com/thomasp85/patchwork,
  <https://patchwork.data-imaginist.com>.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {patchwork: The Composer of Plots},
    author = {Thomas Lin Pedersen},
    year = {2024},
    note = {R package version 1.3.0, 
https://github.com/thomasp85/patchwork},
    url = {https://patchwork.data-imaginist.com},
  }