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
##
##
##
##
# 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
# 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()
)
# 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)