Elaborado por: Luisa María Millán Duque - Especialización Analítica de Datos

#Cargar las librerias

library(readxl)
library(ggplot2)
library(plotly)
## 
## Adjuntando el paquete: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(lmtest)
## Cargando paquete requerido: zoo
## 
## Adjuntando el paquete: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(CGP)
library(readr)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
#Cargar data set
data =read_csv2("C:/Users/luisi/OneDrive/Documents/ESPECIALIZACION/HERRAMIENTAS MINERIA/u3/heart.csv")
## ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.
## Rows: 296 Columns: 14
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ";"
## chr  (1): oldpeak
## dbl (13): age, sex, cp, trestbps, chol, fbs, restecg, thalach, exang, slope,...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Visualización del dataset

head(data)
## # A tibble: 6 × 14
##     age   sex    cp trestbps  chol   fbs restecg thalach exang oldpeak slope
##   <dbl> <dbl> <dbl>    <dbl> <dbl> <dbl>   <dbl>   <dbl> <dbl> <chr>   <dbl>
## 1    63     1     3      145   233     1       0     150     0 2.3         0
## 2    37     1     2      130   250     0       1     187     0 3.5         0
## 3    41     0     1      130   204     0       0     172     0 1.4         2
## 4    56     1     1      120   236     0       1     178     0 0.8         2
## 5    57     0     0      120   354     0       1     163     1 0.6         2
## 6    57     1     0      140   192     0       1     148     0 0.4         1
## # ℹ 3 more variables: ca <dbl>, thal <dbl>, target <dbl>
# 2. Ver las dimensiones (número de filas y columnas)
dim(data)
## [1] 296  14
# 3. Ver los tipos de variables (números, enteros, etc.)
str(data)
## spc_tbl_ [296 × 14] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ age     : num [1:296] 63 37 41 56 57 57 56 44 52 57 ...
##  $ sex     : num [1:296] 1 1 0 1 0 1 0 1 1 1 ...
##  $ cp      : num [1:296] 3 2 1 1 0 0 1 1 2 2 ...
##  $ trestbps: num [1:296] 145 130 130 120 120 140 140 120 172 150 ...
##  $ chol    : num [1:296] 233 250 204 236 354 192 294 263 199 168 ...
##  $ fbs     : num [1:296] 1 0 0 0 0 0 0 0 1 0 ...
##  $ restecg : num [1:296] 0 1 0 1 1 1 0 1 1 1 ...
##  $ thalach : num [1:296] 150 187 172 178 163 148 153 173 162 174 ...
##  $ exang   : num [1:296] 0 0 0 0 1 0 0 0 0 0 ...
##  $ oldpeak : chr [1:296] "2.3" "3.5" "1.4" "0.8" ...
##  $ slope   : num [1:296] 0 0 2 2 2 1 1 2 2 2 ...
##  $ ca      : num [1:296] 0 0 0 0 0 0 0 0 0 0 ...
##  $ thal    : num [1:296] 1 2 2 2 2 1 2 3 3 2 ...
##  $ target  : num [1:296] 1 1 1 1 1 1 1 1 1 1 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   age = col_double(),
##   ..   sex = col_double(),
##   ..   cp = col_double(),
##   ..   trestbps = col_double(),
##   ..   chol = col_double(),
##   ..   fbs = col_double(),
##   ..   restecg = col_double(),
##   ..   thalach = col_double(),
##   ..   exang = col_double(),
##   ..   oldpeak = col_character(),
##   ..   slope = col_double(),
##   ..   ca = col_double(),
##   ..   thal = col_double(),
##   ..   target = col_double()
##   .. )
##  - attr(*, "problems")=<pointer: 0x0000017fbbefef70>
#Asignamos nuevos nombres a variables
data$sex    <- factor(data$sex, labels = c("Mujer", "Hombre"))
data$target <- factor(data$target, labels = c("Sano", "Cardiopatía"))

# Ejecutamos resumen estadístico global
summary(data)
##       age            sex            cp            trestbps          chol      
##  Min.   :29.00   Mujer : 95   Min.   :0.0000   Min.   : 94.0   Min.   :126.0  
##  1st Qu.:48.00   Hombre:201   1st Qu.:0.0000   1st Qu.:120.0   1st Qu.:211.0  
##  Median :56.00                Median :1.0000   Median :130.0   Median :242.5  
##  Mean   :54.52                Mean   :0.9595   Mean   :131.6   Mean   :247.2  
##  3rd Qu.:61.00                3rd Qu.:2.0000   3rd Qu.:140.0   3rd Qu.:275.2  
##  Max.   :77.00                Max.   :3.0000   Max.   :200.0   Max.   :564.0  
##       fbs            restecg          thalach          exang       
##  Min.   :0.0000   Min.   :0.0000   Min.   : 71.0   Min.   :0.0000  
##  1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:133.0   1st Qu.:0.0000  
##  Median :0.0000   Median :1.0000   Median :152.5   Median :0.0000  
##  Mean   :0.1453   Mean   :0.5236   Mean   :149.6   Mean   :0.3277  
##  3rd Qu.:0.0000   3rd Qu.:1.0000   3rd Qu.:166.0   3rd Qu.:1.0000  
##  Max.   :1.0000   Max.   :2.0000   Max.   :202.0   Max.   :1.0000  
##       oldpeak        slope             ca              thal      
##  Length   :296   Min.   :0.000   Min.   :0.0000   Min.   :1.000  
##  N.unique : 40   1st Qu.:1.000   1st Qu.:0.0000   1st Qu.:2.000  
##  N.blank  :  0   Median :1.000   Median :0.0000   Median :2.000  
##  Min.nchar:  1   Mean   :1.395   Mean   :0.6791   Mean   :2.328  
##  Max.nchar:  3   3rd Qu.:2.000   3rd Qu.:1.0000   3rd Qu.:3.000  
##                  Max.   :2.000   Max.   :3.0000   Max.   :3.000  
##          target   
##  Sano       :136  
##  Cardiopatía:160  
##                   
##                   
##                   
## 

Gráfico de Barras - Presencia de Cardiopatía por género

# 1. CÁLCULO ESTADÍSTICO
# Crear tabla de contingencia de frecuencias absolutas (conteo de personas)
tabla_conteo = table(data$target, data$sex)

# Asignar nombres claros a las filas y columnas para el reporte
rownames(tabla_conteo) = c("Sano", "Cardiopatía")
colnames(tabla_conteo) = c("Mujeres", "Hombres")

# Calcular porcentajes por columna (margin = 2 indica proporción dentro de cada sexo)
tabla_porcentaje = prop.table(tabla_conteo, margin = 2) * 100

# Ver resultados estadísticos en la consola
cat("--- Porcentajes calculados por sexo ---\n")
## --- Porcentajes calculados por sexo ---
print(round(tabla_porcentaje, 2))
##              
##               Mujeres Hombres
##   Sano          25.26   55.72
##   Cardiopatía   74.74   44.28
barplot(tabla_porcentaje,
        beside = TRUE,
        col = c("#5DADE2", "#EC7063"),
        main = "Cardiopatía por Sexo en Afiliados SURA",
        xlab = "Sexo Biológico",
        ylab = "Porcentaje dentro del grupo (%)",
        ylim = c(0, 100))

# Agregar leyenda
legend("topright",
       legend = rownames(tabla_porcentaje),
       fill = c("#5DADE2", "#EC7063"),
       bty = "n")

# Agregar una línea guía horizontal en el 50%
abline(h = 50, lty = 3, col = "gray40")

Cálculo de la media de colesterol y cálculo de la desviación estándar según grupo de diagnóstico.

media_col = tapply(data$chol, data$target, mean)
sd_col = tapply(data$chol, data$target, sd)
tabla_resumen = data.frame(
  Grupo_Riesgo = c("Sin Cardiopatía (0)", "Con Cardiopatía (1)"),
  Media_Colesterol = media_col,
  Desv_Estandar = sd_col
)
print(tabla_resumen)
##                    Grupo_Riesgo Media_Colesterol Desv_Estandar
## Sano        Sin Cardiopatía (0)         251.4632      49.65181
## Cardiopatía Con Cardiopatía (1)         243.4938      53.75755

Gráfico de Barras - Clasificación por categoría (Tipo de dolor presentado)

# 1. Preparar únicamente la columna de dolor torácico (cp)
heart_grafico = data %>%
  mutate(
    # Reutilizamos target tal cual ya lo tienes
    Condicion = target, 
    # Etiquetamos el tipo de dolor torácico
    Dolor_Toracico = factor(cp, 
                            levels = c(0, 1, 2, 3),
                            labels = c("Tipo 0\n(Asintomático)", 
                                       "Tipo 1\n(Angina Típica)", 
                                       "Tipo 2\n(Angina Atípica)", 
                                       "Tipo 3\n(No Anginoso)"))
  )

# 2. Generar el gráfico
ggplot(heart_grafico, aes(x = Dolor_Toracico, fill = Condicion)) +
  geom_bar(position = position_dodge(width = 0.85), width = 0.75, color = "black") +
  # Conteo numérico sobre las barras
  geom_text(stat = "count", 
            aes(label = after_stat(count)), 
            position = position_dodge(width = 0.85), 
            vjust = -0.4, 
            fontface = "bold", 
            size = 4) +
  # Asignar colores según los nombres exactos que ya tiene tu columna target
  scale_fill_manual(values = c("Sano" = "#2ECC71", 
                               "Cardiopatía" = "#E74C3C")) +
  labs(
    title = "Distribución de Pacientes Sanos vs. Enfermos según Dolor Torácico",
    x = "Categoría de Dolor Torácico (cp)",
    y = "Número de Pacientes",
    fill = "Condición Clínica"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold", size = 14),
    legend.position = "top",
    panel.grid.minor = element_blank()
  )

Cálculo de media de presión arterial por grupo de dolor

# tapply(variable_numerica, variable_agrupadora, funcion)
medias_presion = tapply(data$trestbps, data$cp, mean)
desv_presion   = tapply(data$trestbps, data$cp, sd)

# Renombrar los grupos de dolor torácico para que sean legibles
nombres_dolor = c("Asintomático", "Angina Típica", "Angina Atípica", "No Anginoso")
names(medias_presion) = nombres_dolor

# Consolidar un resumen estadístico tabular
resumen_presion = data.frame(
  Tipo_Dolor = nombres_dolor,
  Media_mm_Hg = round(medias_presion, 2),
  Desv_Estandar = round(desv_presion, 2)
)

cat("--- Presión arterial sistólica promedio por tipo de dolor ---\n")
## --- Presión arterial sistólica promedio por tipo de dolor ---
print(resumen_presion)
##                    Tipo_Dolor Media_mm_Hg Desv_Estandar
## Asintomático     Asintomático      132.05         18.16
## Angina Típica   Angina Típica      128.47         15.99
## Angina Atípica Angina Atípica      130.13         16.80
## No Anginoso       No Anginoso      140.87         19.57
# 2. GRÁFICO DE BARRAS DE MEDIAS (R-Base)
posiciones_barras = barplot(medias_presion,
        col = "#58D68D",
        main = "Presión Arterial Sistólica Promedio según Síntoma (SURA)",
        xlab = "Tipo de Dolor Torácico (cp)",
        ylab = "Presión Arterial Media (mm Hg)",
        ylim = c(0, 160))

# Agregar una línea horizontal de referencia clínica (140 mm Hg = Hipertensión)
abline(h = 140, col = "red", lty = 2, lwd = 2)
text(x = 2.5, y = 146, labels = "Umbral Hipertensión (140 mm Hg)", col = "red", font = 2)

# Escribir el valor numérico exacto encima de cada barra
text(x = posiciones_barras, 
     y = medias_presion - 15, 
     labels = paste(round(medias_presion, 1), "mmHg"), 
     col = "black", font = 2)