Este trabajo tiene como objetivo analizar diferentes distribuciones de probabilidad discretas y continuas utilizando R Markdown, a partir de datos reales de la ciudad de Guadalajara de Buga.
Se emplean bases de datos de áreas como salud, educación y economía, las cuales son procesadas en R para construir tablas con kable(), gráficos y análisis estadístico.
library(knitr)
library(kableExtra)
# Suma de un vector
sumamanu <- function(vector) {
suma <- 0
for (i in vector) {
suma <- suma + i
}
return(suma)
}
# Media de un vector
mediamanu <- function(vector) {
n <- length(vector)
return(sumamanu(vector) / n)
}
# Raiz cuadrada por Newton-Raphson
raizmanu <- function(numero) {
raiz <- numero / 2
for (i in 1:100) {
raiz <- (raiz + numero / raiz) / 2
}
return(raiz)
}
# Exponencial por serie de Taylor
expomanual <- function(x) {
resultado <- 1
termino <- 1
for (i in 1:150) {
termino <- termino * x / i
resultado <- resultado + termino
}
return(resultado)
}
# Logaritmo natural por serie
logmanual <- function(x) {
y <- (x - 1) / (x + 1)
resultado <- 0
potencia <- y
i <- 1
while (i <= 199) {
resultado <- resultado + potencia / i
potencia <- potencia * y * y
i <- i + 2
}
return(2 * resultado)
}
# Factorial
factorialmanu <- function(n) {
if (n == 0) return(1)
resultado <- 1
for (i in 1:n) {
resultado <- resultado * i
}
return(resultado)
}
# Desviación estándar
desviamanu <- function(vector) {
media <- mediamanu(vector)
n <- length(vector)
suma <- 0
for (i in vector) {
dife <- i - media
suma <- suma + dife * dife
}
return(raizmanu(suma / (n - 1)))
}
# Mínimo de un vector
minmanu <- function(vector) {
m <- vector[1]
for (i in 1:length(vector)) {
if (vector[i] < m) {
m <- vector[i]
}
}
return(m)
}
# Máximo de un vector
maxmanu <- function(vector) {
m <- vector[1]
for (i in 1:length(vector)) {
if (vector[i] > m) {
m <- vector[i]
}
}
return(m)
}
# Secuencia de n puntos entre dos valores
seqmanu <- function(desde, hasta, npuntos) {
paso <- (hasta - desde) / (npuntos - 1)
resultado <- c()
for (i in 0:(npuntos - 1)) {
resultado <- c(resultado, desde + i * paso)
}
return(resultado)
}
# Constante pi
numeropi <- 3.141592653589793Surge en procesos donde el cambio es multiplicativo y no aditivo. Se define a partir de una variable \(X\) tal que su logaritmo natural, \(\ln(X)\), sigue una distribución normal. Este modelo es esencial para variables que solo pueden tomar valores positivos y que presentan una asimetría pronunciada hacia la derecha.
La densidad se expresa como:
\[f(x) = \frac{1}{x\,\sigma\sqrt{2\pi}} \exp\!\left( -\frac{(\ln x - \mu)^2}{2\sigma^2} \right)\]
A diferencia de la normal, su media siempre es mayor que su mediana. Esto la hace adecuada para modelar fenómenos con frecuentes valores bajos pero con presencia de valores extremos muy altos, como la distribución de ingresos, el precio de activos financieros o la duración de procesos biológicos.
Para el análisis de la distribución Lognormal se utilizaron datos del impuesto predial de Guadalajara de Buga. La variable seleccionada fue el avalúo catastral de los predios, debido a que representa valores positivos y presenta asimetría hacia la derecha, característica típica de una distribución lognormal.
predio <- c("PREDIO URBANO","CORREGIMIENTO 06","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO RURAL","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"CORREGIMIENTO 06","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO RURAL","PREDIO URBANO","PREDIO URBANO",
"PREDIO URBANO","PREDIO URBANO","PREDIO URBANO")
estrato <- c("1","SIN INFORMACION","4","1","3","SIN INFORMACION","1","1",
"SIN INFORMACION","1","3","3","2","2","2","3","3","1","1","1",
"SIN INFORMACION","1","3","2","1","1","1","3","1","3","1","1",
"1","SIN INFORMACION","2","1","2","2","2")
avaluo <- c(9046000,5764000,15224000,80079000,57205000,10996000,30171000,
23126000,296831000,59354000,49835000,48282000,25099000,31636000,
74738000,108501000,107093000,17326000,494000,31550000,590000,
53381000,79756000,25459000,494000,494000,66862000,64780000,
52993000,57205000,47999000,494000,52601000,29256000,62715000,
71094000,33128000,45378000,63625000)
datoslognormal <- data.frame(
Tipo_Predio = predio,
Estrato = estrato,
Avaluo = avaluo
)
kable(datoslognormal,
caption = "Tabla 1. Avalúos catastrales - Impuesto predial Buga") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, font_size = 13) %>%
scroll_box(height = "300px")| Tipo_Predio | Estrato | Avaluo |
|---|---|---|
| PREDIO URBANO | 1 | 9046000 |
| CORREGIMIENTO 06 | SIN INFORMACION | 5764000 |
| PREDIO URBANO | 4 | 15224000 |
| PREDIO URBANO | 1 | 80079000 |
| PREDIO URBANO | 3 | 57205000 |
| PREDIO RURAL | SIN INFORMACION | 10996000 |
| PREDIO URBANO | 1 | 30171000 |
| PREDIO URBANO | 1 | 23126000 |
| PREDIO URBANO | SIN INFORMACION | 296831000 |
| PREDIO URBANO | 1 | 59354000 |
| PREDIO URBANO | 3 | 49835000 |
| PREDIO URBANO | 3 | 48282000 |
| PREDIO URBANO | 2 | 25099000 |
| PREDIO URBANO | 2 | 31636000 |
| PREDIO URBANO | 2 | 74738000 |
| PREDIO URBANO | 3 | 108501000 |
| PREDIO URBANO | 3 | 107093000 |
| PREDIO URBANO | 1 | 17326000 |
| PREDIO URBANO | 1 | 494000 |
| PREDIO URBANO | 1 | 31550000 |
| CORREGIMIENTO 06 | SIN INFORMACION | 590000 |
| PREDIO URBANO | 1 | 53381000 |
| PREDIO URBANO | 3 | 79756000 |
| PREDIO URBANO | 2 | 25459000 |
| PREDIO URBANO | 1 | 494000 |
| PREDIO URBANO | 1 | 494000 |
| PREDIO URBANO | 1 | 66862000 |
| PREDIO URBANO | 3 | 64780000 |
| PREDIO URBANO | 1 | 52993000 |
| PREDIO URBANO | 3 | 57205000 |
| PREDIO URBANO | 1 | 47999000 |
| PREDIO URBANO | 1 | 494000 |
| PREDIO URBANO | 1 | 52601000 |
| PREDIO RURAL | SIN INFORMACION | 29256000 |
| PREDIO URBANO | 2 | 62715000 |
| PREDIO URBANO | 1 | 71094000 |
| PREDIO URBANO | 2 | 33128000 |
| PREDIO URBANO | 2 | 45378000 |
| PREDIO URBANO | 2 | 63625000 |
Aunque el data frame contiene variables de contexto como el tipo de predio y el estrato social, la distribución Lognormal se aplicó únicamente sobre la variable avalúo.
# Calculamos el logaritmo natural de cada avaluo
logavaluo <- c()
for (i in 1:length(avaluo)) {
logavaluo <- c(logavaluo, logmanual(avaluo[i]))
}
# Parametros de la distribucion lognormal
mu <- mediamanu(logavaluo)
sigma <- desviamanu(logavaluo)
tablaparam <- data.frame(
Parametro = c("mu (media de los logaritmos)", "sigma (desv. de los logaritmos)"),
Valor = c(round(mu, 4), round(sigma, 4))
)
kable(tablaparam,
caption = "Parámetros estimados - Distribución lognormal") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Parametro | Valor |
|---|---|
| mu (media de los logaritmos) | 6.5686 |
| sigma (desv. de los logaritmos) | 0.0003 |
Se calcularon los parámetros de la distribución Lognormal usando el logaritmo natural de los avalúos.
# Funcion de densidad lognormal programada manualmente
lognormalmanu <- function(x, mu, sigma) {
parte1 <- 1 / (x * sigma * raizmanu(2 * numeropi))
exponente <- -((logmanual(x) - mu)^2) / (2 * sigma^2)
parte2 <- expomanual(exponente)
return(parte1 * parte2)
}Comparamos nuestra función con la de R:
valorprueba <- 9046000
comparacionln <- data.frame(
Valor = valorprueba,
Manual = lognormalmanu(valorprueba, mu, sigma),
R = dlnorm(valorprueba, meanlog = mu, sdlog = sigma)
)
kable(comparacionln,
caption = "Tabla 2. Comparación función manual vs R - Lognormal",
digits = 15) %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Valor | Manual | R |
|---|---|---|
| 9046000 | 0.0001629094 | 0 |
Tenemos como resultado que las dos funciones arrojan el mismo valor.
Para la distribución Lognormal la gráfica más apropiada es el histograma de densidad con la curva teórica superpuesta, ya que permite ver visualmente la asimetría hacia la derecha que caracteriza esta distribución.
hist(datoslognormal$Avaluo,
probability = TRUE,
main = "Distribución Lognormal - Avalúo catastral",
xlab = "Avalúo (COP)",
col = "#AED6F1",
border = "white",
breaks = 12)
xmin <- minmanu(datoslognormal$Avaluo) * 0.5
xmax <- maxmanu(datoslognormal$Avaluo) * 1.1
xseq <- seqmanu(xmin, xmax, 300)
yseq <- c()
for (i in 1:length(xseq)) {
yseq <- c(yseq, lognormalmanu(xseq[i], mu, sigma))
}
lines(xseq, yseq, col = "#154360", lwd = 3)Los avalúos prediales presentan características de una distribución Lognormal: datos estrictamente positivos y clara asimetría hacia la derecha. La función programada manualmente presentó resultados equivalentes a la función incorporada en R.
Este modelo se fundamenta en el Teorema del Límite Central, el cual establece que la suma de variables independientes con varianza finita tiende a esta distribución a medida que el número de observaciones crece. Se caracteriza por ser la distribución de máxima incertidumbre para una media y varianza dadas.
Su función de densidad de probabilidad es:
\[f(x) = \frac{1}{\sigma\sqrt{2\pi}}\; e^{-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^2}\]
Para el análisis de la distribución Normal se utilizaron datos de nacidos vivos en Guadalajara de Buga durante 2025. La variable principal fue el peso al nacer (kg).
sexo <- c("MASCULINO","FEMENINO","MASCULINO","MASCULINO","FEMENINO",
"MASCULINO","MASCULINO","MASCULINO","FEMENINO","MASCULINO",
"FEMENINO","FEMENINO","MASCULINO","FEMENINO","FEMENINO",
"MASCULINO","MASCULINO","FEMENINO","FEMENINO")
peso <- c(3.695, 2.530, 3.605, 3.275, 2.675,
3.170, 3.255, 2.940, 2.730, 2.870,
2.670, 2.445, 3.060, 3.620, 2.905,
3.700, 3.795, 3.250, 3.480)
datosgaussiana <- data.frame(Sexo = sexo, PesoNac = peso)
kable(datosgaussiana,
caption = "Tabla 3. Peso al nacer - Nacidos vivos Buga 2025") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, font_size = 13) %>%
scroll_box(height = "250px")| Sexo | PesoNac |
|---|---|
| MASCULINO | 3.695 |
| FEMENINO | 2.530 |
| MASCULINO | 3.605 |
| MASCULINO | 3.275 |
| FEMENINO | 2.675 |
| MASCULINO | 3.170 |
| MASCULINO | 3.255 |
| MASCULINO | 2.940 |
| FEMENINO | 2.730 |
| MASCULINO | 2.870 |
| FEMENINO | 2.670 |
| FEMENINO | 2.445 |
| MASCULINO | 3.060 |
| FEMENINO | 3.620 |
| FEMENINO | 2.905 |
| MASCULINO | 3.700 |
| MASCULINO | 3.795 |
| FEMENINO | 3.250 |
| FEMENINO | 3.480 |
Aunque el data frame incluye la variable sexo, la distribución Normal se aplicó únicamente sobre el peso al nacer.
mediapeso <- mediamanu(datosgaussiana$PesoNac)
sigmapeso <- desviamanu(datosgaussiana$PesoNac)
tablaparamnorm <- data.frame(
Parametro = c("mu (media del peso en kg)", "sigma (desv. est. en kg)"),
Valor = c(round(mediapeso, 4), round(sigmapeso, 4))
)
kable(tablaparamnorm,
caption = "Parámetros estimados - Distribución normal") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Parametro | Valor |
|---|---|
| mu (media del peso en kg) | 3.1405 |
| sigma (desv. est. en kg) | 0.4277 |
# Funcion de densidad normal programada manualmente
distrinormal <- function(x, media, sigma) {
parte1 <- 1 / (sigma * raizmanu(2 * numeropi))
dife <- x - media
exponente <- -((dife * dife) / (2 * sigma * sigma))
parte2 <- expomanual(exponente)
return(parte1 * parte2)
}Ahora realizamos la comparación de la función de la distribución Gaussiana realizada manualmente con la función que viene incluida en RStudio.
valorpruebag <- 3.695
comparaciong <- data.frame(
Valor = valorpruebag,
Manual = distrinormal(valorpruebag, mediapeso, sigmapeso),
R = dnorm(valorpruebag, mean = mediapeso, sd = sigmapeso)
)
kable(comparaciong,
caption = "Tabla 4. Comparación función manual vs R - Normal",
digits = 10) %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Valor | Manual | R |
|---|---|---|
| 3.695 | 0.4025269 | 0.4025269 |
Tenemos como resultado que las dos funciones arrojan el mismo valor.
Para la distribución Normal la gráfica más apropiada es el histograma de densidad con curva de campana superpuesta, ya que permite observar visualmente la simetría alrededor de la media y la forma característica de campana de Gauss.
hist(datosgaussiana$PesoNac,
probability = TRUE,
main = "Distribución Normal - Peso al nacer (kg)",
xlab = "Peso (kg)",
col = "#AED6F1",
border = "white",
breaks = 8)
xming <- minmanu(datosgaussiana$PesoNac) - 0.5
xmaxg <- maxmanu(datosgaussiana$PesoNac) + 0.5
xseqg <- seqmanu(xming, xmaxg, 300)
yseqg <- c()
for (i in 1:length(xseqg)) {
yseqg <- c(yseqg, distrinormal(xseqg[i], mediapeso, sigmapeso))
}
lines(xseqg, yseqg, col = "#154360", lwd = 3)El peso al nacer presentó un comportamiento cercano a una distribución Normal, concentrándose alrededor de la media calculada. La función programada manualmente presentó resultados equivalentes a la función de R.
Es una distribución de muestreo que se obtiene al sumar los cuadrados de \(k\) variables aleatorias normales estándar independientes. Su comportamiento está regido por el parámetro \(k\), denominado grados de libertad.
A medida que \(k\) aumenta, la distribución gana simetría y se aproxima a una normal. Su utilidad principal reside en las pruebas de independencia, donde se mide cuánto se desvían los datos observados de los esperados bajo una hipótesis.
\[\chi^2 = \sum \frac{(O - E)^2}{E}\]
Para la distribución Chi-cuadrado se utilizaron datos de instituciones educativas públicas de Guadalajara de Buga. Se analizó la relación entre zona geográfica (Urbana/Rural) y nivel educativo ofrecido.
zona <- c("Urbana","Urbana","Urbana","Urbana",
"Rural","Rural","Rural","Rural","Rural","Rural",
"Rural","Rural","Rural","Rural","Rural","Rural",
"Rural","Rural","Rural","Rural")
nivel <- c("Media","Media","Secundaria","Secundaria",
"Media","Primaria","Primaria","Primaria","Primaria","Completo",
"Primaria","Secundaria","Primaria","Completo","Secundaria",
"Media","Secundaria","Secundaria","Primaria","Completo")
datoschi <- data.frame(Zona = zona, Nivel = nivel)
kable(datoschi,
caption = "Tabla 5. Instituciones educativas - Zona y nivel") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, font_size = 13) %>%
scroll_box(height = "250px")| Zona | Nivel |
|---|---|
| Urbana | Media |
| Urbana | Media |
| Urbana | Secundaria |
| Urbana | Secundaria |
| Rural | Media |
| Rural | Primaria |
| Rural | Primaria |
| Rural | Primaria |
| Rural | Primaria |
| Rural | Completo |
| Rural | Primaria |
| Rural | Secundaria |
| Rural | Primaria |
| Rural | Completo |
| Rural | Secundaria |
| Rural | Media |
| Rural | Secundaria |
| Rural | Secundaria |
| Rural | Primaria |
| Rural | Completo |
Contamos las frecuencias de cada combinación zona-nivel de forma manual, recorriendo el data frame fila por fila:
ntotal <- length(datoschi$Zona)
# Conteos por combinacion
urbmedia <- 0
urbsecundaria <- 0
urbprimaria <- 0
urbcompleto <- 0
ruralmedia <- 0
ruralsecundaria <- 0
ruralprimaria <- 0
ruralcompleto <- 0
for (i in 1:ntotal) {
if (datoschi$Zona[i] == "Urbana") {
if (datoschi$Nivel[i] == "Media") { urbmedia <- urbmedia + 1 }
if (datoschi$Nivel[i] == "Secundaria") { urbsecundaria <- urbsecundaria + 1 }
if (datoschi$Nivel[i] == "Primaria") { urbprimaria <- urbprimaria + 1 }
if (datoschi$Nivel[i] == "Completo") { urbcompleto <- urbcompleto + 1 }
}
if (datoschi$Zona[i] == "Rural") {
if (datoschi$Nivel[i] == "Media") { ruralmedia <- ruralmedia + 1 }
if (datoschi$Nivel[i] == "Secundaria") { ruralsecundaria <- ruralsecundaria + 1 }
if (datoschi$Nivel[i] == "Primaria") { ruralprimaria <- ruralprimaria + 1 }
if (datoschi$Nivel[i] == "Completo") { ruralcompleto <- ruralcompleto + 1 }
}
}
# Tabla de frecuencias observadas
obs <- data.frame(
Zona = c("Urbana", "Rural"),
Media = c(urbmedia, ruralmedia),
Secundaria = c(urbsecundaria, ruralsecundaria),
Primaria = c(urbprimaria, ruralprimaria),
Completo = c(urbcompleto, ruralcompleto)
)
kable(obs,
caption = "Tabla 6. Frecuencias observadas") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Zona | Media | Secundaria | Primaria | Completo |
|---|---|---|---|---|
| Urbana | 2 | 2 | 0 | 0 |
| Rural | 2 | 4 | 7 | 3 |
# Totales por fila
totalurbana <- urbmedia + urbsecundaria + urbprimaria + urbcompleto
totalrural <- ruralmedia + ruralsecundaria + ruralprimaria + ruralcompleto
# Totales por columna
totalmedia <- urbmedia + ruralmedia
totalsecundaria <- urbsecundaria + ruralsecundaria
totalprimaria <- urbprimaria + ruralprimaria
totalcompleto <- urbcompleto + ruralcompleto
# Frecuencias esperadas
eurmedia <- (totalurbana * totalmedia) / ntotal
eursecundaria <- (totalurbana * totalsecundaria) / ntotal
eurprimaria <- (totalurbana * totalprimaria) / ntotal
eurcompleto <- (totalurbana * totalcompleto) / ntotal
erumedia <- (totalrural * totalmedia) / ntotal
erusecundaria <- (totalrural * totalsecundaria) / ntotal
eruprimaria <- (totalrural * totalprimaria) / ntotal
erucompleto <- (totalrural * totalcompleto) / ntotal
esp <- data.frame(
Zona = c("Urbana", "Rural"),
Media = c(round(eurmedia, 3), round(erumedia, 3)),
Secundaria = c(round(eursecundaria, 3), round(erusecundaria, 3)),
Primaria = c(round(eurprimaria, 3), round(eruprimaria, 3)),
Completo = c(round(eurcompleto, 3), round(erucompleto, 3))
)
kable(esp,
caption = "Tabla 7. Frecuencias esperadas") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Zona | Media | Secundaria | Primaria | Completo |
|---|---|---|---|---|
| Urbana | 0.8 | 1.2 | 1.4 | 0.6 |
| Rural | 3.2 | 4.8 | 5.6 | 2.4 |
# Estadistico chi-cuadrado: suma de (O-E)^2 / E para cada celda
chimanual <- 0
chimanual <- chimanual + (urbmedia - eurmedia)^2 / eurmedia
chimanual <- chimanual + (urbsecundaria - eursecundaria)^2 / eursecundaria
chimanual <- chimanual + (urbprimaria - eurprimaria)^2 / eurprimaria
chimanual <- chimanual + (urbcompleto - eurcompleto)^2 / eurcompleto
chimanual <- chimanual + (ruralmedia - erumedia)^2 / erumedia
chimanual <- chimanual + (ruralsecundaria - erusecundaria)^2 / erusecundaria
chimanual <- chimanual + (ruralprimaria - eruprimaria)^2 / eruprimaria
chimanual <- chimanual + (ruralcompleto - erucompleto)^2 / erucompleto
# Grados de libertad: (2 filas - 1) * (4 columnas - 1) = 3
gl <- 3
resultadochi <- data.frame(
Estadistico = c("Chi-cuadrado manual", "Grados de libertad"),
Valor = c(round(chimanual, 6), gl)
)
kable(resultadochi,
caption = "Tabla 8. Resultado prueba Chi-cuadrado") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Estadistico | Valor |
|---|---|
| Chi-cuadrado manual | 5.416667 |
| Grados de libertad | 3.000000 |
Ahora comparamos la función elaborada manualmente con la función propia de RStudio.
## Warning in chisq.test(table(datoschi$Zona, datoschi$Nivel), simulate.p.value =
## FALSE): Chi-squared approximation may be incorrect
comparacionchi <- data.frame(
Manual = round(chimanual, 6),
R = round(chiR, 6)
)
kable(comparacionchi,
caption = "Tabla 9. Comparación Chi-cuadrado manual vs R") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Manual | R | |
|---|---|---|
| X-squared | 5.416667 | 5.416667 |
R presenta una advertencia por el tamaño reducido de la muestra; sin embargo, ambos métodos arrojan el mismo estadístico.
Para la distribución Chi-cuadrado la gráfica más apropiada es el gráfico de barras agrupadas, ya que permite comparar visualmente las frecuencias de dos variables categóricas (zona y nivel educativo) una al lado de la otra.
vurbana <- c(urbmedia, urbsecundaria, urbprimaria, urbcompleto)
vrural <- c(ruralmedia, ruralsecundaria, ruralprimaria, ruralcompleto)
barplot(rbind(vurbana, vrural),
beside = TRUE,
names.arg = c("Media", "Secundaria", "Primaria", "Completo"),
main = "Zona geográfica vs Nivel educativo",
xlab = "Nivel educativo",
ylab = "Frecuencia",
col = c("#AED6F1", "#154360"),
legend.text = c("Urbana", "Rural"),
args.legend = list(x = "topright"))La prueba Chi-cuadrado permitió analizar la relación entre zona geográfica y niveles educativos ofrecidos. Los resultados obtenidos manualmente fueron equivalentes a los calculados por R.
Este modelo describe el número de veces que ocurre un evento en un intervalo determinado de tiempo o espacio. Se deriva como el límite de una distribución Binomial cuando el número de ensayos es muy elevado y la probabilidad de éxito es muy pequeña, manteniendo una tasa promedio constante \(\lambda\).
Su función de masa de probabilidad es:
\[P(X = k) = \frac{e^{-\lambda}\, \lambda^k}{k!}\]
Para la distribución de Poisson se utilizaron datos de accidentalidad vial de Guadalajara de Buga. La variable de análisis es el número de accidentes por día durante el mes de enero.
accidentesdia <- c(1, 0, 2, 3, 3, 1, 2,
3, 0, 1, 2, 2, 1, 0,
1, 0, 1, 2, 2, 0, 2,
0, 2, 0, 0, 2, 0, 0,
0, 1, 0)
datospoisson <- data.frame(
Dia = 1:31,
AccidentesDia = accidentesdia
)
kable(datospoisson,
caption = "Tabla 10. Accidentes viales diarios - Buga, enero") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, font_size = 13) %>%
scroll_box(height = "250px")| Dia | AccidentesDia |
|---|---|
| 1 | 1 |
| 2 | 0 |
| 3 | 2 |
| 4 | 3 |
| 5 | 3 |
| 6 | 1 |
| 7 | 2 |
| 8 | 3 |
| 9 | 0 |
| 10 | 1 |
| 11 | 2 |
| 12 | 2 |
| 13 | 1 |
| 14 | 0 |
| 15 | 1 |
| 16 | 0 |
| 17 | 1 |
| 18 | 2 |
| 19 | 2 |
| 20 | 0 |
| 21 | 2 |
| 22 | 0 |
| 23 | 2 |
| 24 | 0 |
| 25 | 0 |
| 26 | 2 |
| 27 | 0 |
| 28 | 0 |
| 29 | 0 |
| 30 | 1 |
| 31 | 0 |
lam <- mediamanu(datospoisson$AccidentesDia)
tablaparamP <- data.frame(
Parametro = "lambda (tasa media diaria de accidentes)",
Valor = round(lam, 4)
)
kable(tablaparamP,
caption = "Parámetro estimado - Distribución Poisson") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| Parametro | Valor |
|---|---|
| lambda (tasa media diaria de accidentes) | 1.0968 |
# Funcion de masa de probabilidad Poisson programada manualmente
poissonmanu <- function(k, lambda) {
eneglambda <- expomanual(-lambda)
lambdak <- 1
if (k > 0) {
for (i in 1:k) {
lambdak <- lambdak * lambda
}
}
kfact <- factorialmanu(k)
return(eneglambda * lambdak / kfact)
}Calculamos la probabilidad para cada valor posible de \(k\) (de 0 a 6 accidentes):
kvals <- 0:6
probmanu <- c()
probr <- c()
for (k in kvals) {
probmanu <- c(probmanu, poissonmanu(k, lam))
probr <- c(probr, dpois(k, lambda = lam))
}
tablapoisson <- data.frame(
k = kvals,
Manual = round(probmanu, 6),
R = round(probr, 6)
)
kable(tablapoisson,
caption = "Tabla 11. Comparación P(X=k) manual vs R - Poisson") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| k | Manual | R |
|---|---|---|
| 0 | 0.333947 | 0.333947 |
| 1 | 0.366264 | 0.366264 |
| 2 | 0.200854 | 0.200854 |
| 3 | 0.073431 | 0.073431 |
| 4 | 0.020134 | 0.020134 |
| 5 | 0.004417 | 0.004417 |
| 6 | 0.000807 | 0.000807 |
Tenemos como resultado que las dos funciones arrojan los mismos valores.
Para la distribución de Poisson la gráfica más apropiada es el gráfico de barras comparando frecuencias observadas vs teóricas, ya que Poisson es una distribución discreta (cuenta eventos enteros) y las barras representan mejor cada valor posible de \(k\).
frecobs <- c()
for (k in kvals) {
conteo <- 0
for (i in 1:length(datospoisson$AccidentesDia)) {
if (datospoisson$AccidentesDia[i] == k) {
conteo <- conteo + 1
}
}
frecobs <- c(frecobs, conteo)
}
barplot(rbind(frecobs, probmanu * length(datospoisson$AccidentesDia)),
beside = TRUE,
names.arg = kvals,
main = "Distribución Poisson - Accidentes diarios en Buga",
xlab = "Número de accidentes (k)",
ylab = "Frecuencia",
col = c("#AED6F1", "#154360"),
legend.text = c("Observado", "Teórico Poisson"),
args.legend = list(x = "topright"))El número de accidentes viales diarios en Buga durante enero sigue una distribución de Poisson. La función programada manualmente presentó resultados equivalentes a la función de R.
Esta distribución es la contraparte continua de la de Poisson y modela el tiempo de espera entre dos eventos sucesivos. Su característica analítica más importante es la falta de memoria, lo cual implica que la probabilidad de que ocurra un evento en el futuro es totalmente independiente del tiempo que ya haya transcurrido.
Su función de densidad es:
\[f(x) = \lambda\, e^{-\lambda x}, \quad x \geq 0\]
Para la distribución Exponencial se utilizaron datos de defunciones registradas en Guadalajara de Buga durante enero de 2025. La variable de análisis es el tiempo transcurrido entre fallecimientos consecutivos (en horas).
tiemposentre <- c(
1.17, 0.17, 29.33, 0.58, 1.75, 5.08, 2.83,
27.15, 5.85, 0.42, 0.25, 17.83, 0.63, 1.9,
0.48, 6.57, 4.3, 2.45, 2.92, 2.92, 6.42,
8.28, 1.22, 4.67, 0.92, 2.58, 2.17, 6.67,
5.5, 4.17, 13.5, 6.33, 4.0, 2.95, 1.28,
1.6, 1.17, 11.75, 6.25, 10.0, 2.58, 2.17,
4.15, 0.1, 27.83, 6.17, 5.0, 14.77, 0.4,
8.83, 0.5, 3.75, 0.5, 4.92, 0.83, 3.05,
18.78, 1.63, 1.53, 0.33, 5.12, 7.1, 15.82,
3.13, 0.15, 6.35, 5.25, 5.25, 1.58, 0.03,
0.5, 4.82, 1.4, 8.68, 8.65, 1.17, 3.42,
5.33, 0.42, 3.53, 7.18, 0.53, 0.18, 0.57,
0.25, 2.83, 2.25, 3.5, 0.43, 11.38, 10.35,
1.67, 6.17, 1.42, 14.17, 1.33, 15.25, 3.9,
13.93, 8.37, 33.8, 5.5, 5.0, 0.3, 12.53,
3.63, 2.93, 6.18, 9.77, 1.92, 3.9, 7.58,
3.4, 8.68, 0.5, 12.92, 4.0, 2.45, 5.3,
17.33, 14.03, 0.88, 4.25, 0.5, 6.63, 9.37,
3.5, 2.5, 0.87, 5.3, 13.0, 6.33, 0.5
)
datosintervalos <- data.frame(
Intervalo = 1:length(tiemposentre),
TiempoHoras = tiemposentre
)
kable(datosintervalos,
caption = "Tabla 12. Tiempo entre fallecimientos consecutivos - Buga, enero 2025 (horas)",
col.names = c("Intervalo N", "Tiempo (horas)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, font_size = 13) %>%
scroll_box(height = "300px")| Intervalo N | Tiempo (horas) |
|---|---|
| 1 | 1.17 |
| 2 | 0.17 |
| 3 | 29.33 |
| 4 | 0.58 |
| 5 | 1.75 |
| 6 | 5.08 |
| 7 | 2.83 |
| 8 | 27.15 |
| 9 | 5.85 |
| 10 | 0.42 |
| 11 | 0.25 |
| 12 | 17.83 |
| 13 | 0.63 |
| 14 | 1.90 |
| 15 | 0.48 |
| 16 | 6.57 |
| 17 | 4.30 |
| 18 | 2.45 |
| 19 | 2.92 |
| 20 | 2.92 |
| 21 | 6.42 |
| 22 | 8.28 |
| 23 | 1.22 |
| 24 | 4.67 |
| 25 | 0.92 |
| 26 | 2.58 |
| 27 | 2.17 |
| 28 | 6.67 |
| 29 | 5.50 |
| 30 | 4.17 |
| 31 | 13.50 |
| 32 | 6.33 |
| 33 | 4.00 |
| 34 | 2.95 |
| 35 | 1.28 |
| 36 | 1.60 |
| 37 | 1.17 |
| 38 | 11.75 |
| 39 | 6.25 |
| 40 | 10.00 |
| 41 | 2.58 |
| 42 | 2.17 |
| 43 | 4.15 |
| 44 | 0.10 |
| 45 | 27.83 |
| 46 | 6.17 |
| 47 | 5.00 |
| 48 | 14.77 |
| 49 | 0.40 |
| 50 | 8.83 |
| 51 | 0.50 |
| 52 | 3.75 |
| 53 | 0.50 |
| 54 | 4.92 |
| 55 | 0.83 |
| 56 | 3.05 |
| 57 | 18.78 |
| 58 | 1.63 |
| 59 | 1.53 |
| 60 | 0.33 |
| 61 | 5.12 |
| 62 | 7.10 |
| 63 | 15.82 |
| 64 | 3.13 |
| 65 | 0.15 |
| 66 | 6.35 |
| 67 | 5.25 |
| 68 | 5.25 |
| 69 | 1.58 |
| 70 | 0.03 |
| 71 | 0.50 |
| 72 | 4.82 |
| 73 | 1.40 |
| 74 | 8.68 |
| 75 | 8.65 |
| 76 | 1.17 |
| 77 | 3.42 |
| 78 | 5.33 |
| 79 | 0.42 |
| 80 | 3.53 |
| 81 | 7.18 |
| 82 | 0.53 |
| 83 | 0.18 |
| 84 | 0.57 |
| 85 | 0.25 |
| 86 | 2.83 |
| 87 | 2.25 |
| 88 | 3.50 |
| 89 | 0.43 |
| 90 | 11.38 |
| 91 | 10.35 |
| 92 | 1.67 |
| 93 | 6.17 |
| 94 | 1.42 |
| 95 | 14.17 |
| 96 | 1.33 |
| 97 | 15.25 |
| 98 | 3.90 |
| 99 | 13.93 |
| 100 | 8.37 |
| 101 | 33.80 |
| 102 | 5.50 |
| 103 | 5.00 |
| 104 | 0.30 |
| 105 | 12.53 |
| 106 | 3.63 |
| 107 | 2.93 |
| 108 | 6.18 |
| 109 | 9.77 |
| 110 | 1.92 |
| 111 | 3.90 |
| 112 | 7.58 |
| 113 | 3.40 |
| 114 | 8.68 |
| 115 | 0.50 |
| 116 | 12.92 |
| 117 | 4.00 |
| 118 | 2.45 |
| 119 | 5.30 |
| 120 | 17.33 |
| 121 | 14.03 |
| 122 | 0.88 |
| 123 | 4.25 |
| 124 | 0.50 |
| 125 | 6.63 |
| 126 | 9.37 |
| 127 | 3.50 |
| 128 | 2.50 |
| 129 | 0.87 |
| 130 | 5.30 |
| 131 | 13.00 |
| 132 | 6.33 |
| 133 | 0.50 |
## [1] 5.507293
## [1] 0.1815774
# f(x) = lambda * e^(-lambda * x)
exponencialmanu <- function(x, lambda) {
return(lambda * expomanual(-lambda * x))
}Comparamos nuestra función con la de R para varios valores de \(x\):
xprueba <- c( 1.17, 0.17, 29.33, 0.58, 1.75)
manuvals <- c()
rvals <- c()
for (xi in xprueba) {
manuvals <- c(manuvals, exponencialmanu(xi, lambdae))
rvals <- c(rvals, dexp(xi, rate = lambdae))
}
comparacionexp <- data.frame(
x = xprueba,
fmanual = round(manuvals, 8),
fR = round(rvals, 8)
)
kable(comparacionexp,
caption = "Tabla 13. Comparación f(x) manual vs R - Exponencial") %>%
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE, font_size = 13)| x | fmanual | fR |
|---|---|---|
| 1.17 | 0.1468243 | 0.1468243 |
| 0.17 | 0.1760581 | 0.1760581 |
| 29.33 | 0.0008834 | 0.0008834 |
| 0.58 | 0.1634271 | 0.1634271 |
| 1.75 | 0.1321479 | 0.1321479 |
Tenemos como resultado que las dos distribuciones arrojan el mismo resultado.
Para la distribución exponencial la gráfica más apropiada es el histograma de densidad con curva de decaimiento superpuesta, ya que permite observar la caída rápida al inicio (muchos tiempos de espera cortos) y la cola hacia la derecha (pocos tiempos muy largos).
hist(datosintervalos$TiempoHoras,
probability = TRUE,
main = "Distribución Exponencial - Tiempo entre defunciones (horas)",
xlab = "Tiempo (horas)",
col = "#AED6F1",
border = "white",
breaks = 8)
inicioe <- 0
fine <- maxmanu(datosintervalos$TiempoHoras) * 1.1
xseqe <- seqmanu(inicioe, fine, 300)
yseqe <- c()
for (xi in xseqe) {
yseqe <- c(yseqe, exponencialmanu(xi, lambdae))
}
lines(xseqe, yseqe, col = "#154360", lwd = 3)La función programada manualmente presentó resultados equivalentes a la función de R.
A lo largo de este trabajo se analizaron cinco distribuciones de probabilidad :lognormal, normal, Chi-cuadrado, Poisson y exponencial, aplicadas a datos reales de Guadalajara de Buga. En todos los casos:
kableExtra para presentar los datos de forma
organizada y visualmente clara.Accidentalidad vial Guadalajara de Buga | Datos abiertos Colombia. (2026, 6 mayo). https://www.datos.gov.co/Transporte/Accidentalidad-Vial-Guadalajara-De-Buga/99gi-pnyn/about_data
Directorio instituciones educativas públicas del municipio de Guadalajara de Buga / Directory of public educational institutions in the municipality of Guadalajara de Buga | Datos Abiertos Colombia. (2026, 5 marzo). https://www.datos.gov.co/Educaci-n/Directorio-instituciones-educativas-p-blicas-del-m/fmaq-a76w/about_data
Guadalajara de Buga : Defunciones año 2025 | Datos Abiertos Colombia. (2025, 11 noviembre). https://www.datos.gov.co/Salud-y-Protecci-n-Social/Guadalajara-de-Buga-Defunciones-a-o-2025/y7y4-itpy/about_data
Guadalajara de Buga : Impuesto Predial 2001 - 2005 | Datos Abiertos Colombia. (2023, 22 agosto). https://www.datos.gov.co/Hacienda-y-Cr-dito-P-blico/Guadalajara-de-Buga-Impuesto-Predial-2001-2005/rghm-yzev/about_data
Guadalajara de Buga : Nacidos vivos 2025 | Datos abiertos Colombia. (2025, 5 noviembre). https://www.datos.gov.co/Salud-y-Protecci-n-Social/Guadalajara-de-Buga-Nacidos-Vivos-2025/dc6m-g67k/about_data
Casella, G., & Berger, R. L. (2002). Statistical Inference. Duxbury.
Ross, S. M. (2014). Introduction to Probability Models. Academic Press.
Walpole, R. E., Myers, R. H., Myers, S. L., & Ye, K. (2012). Probability & Statistics for Engineers & Scientists. Pearson.
Devore, J. L. (2016). Probability and Statistics for Engineering and the Sciences. Cengage Learning.
R Core Team (2024). R: A language and environment for statistical computing. R Foundation for Statistical Computing.