1 Introducción

El ruido ambiental es uno de los factores de contaminación más frecuentemente ignorados en entornos urbanos y académicos. Niveles elevados de ruido pueden afectar la concentración, el aprendizaje y la salud de quienes habitan o transitan los espacios de una institución educativa.

Este informe presenta un análisis exploratorio de los niveles de presión sonora (dB) registrados en dos zonas del campus universitario:

  • 🟢 Ciencias – zona de facultades de ciencias exactas y naturales.
  • 🟣 Licenciatura – zona de humanidades y ciencias sociales.

Los datos fueron recolectados mediante el micrófono integrado de un teléfono móvil, registrando el nivel de presión sonora en decibeles (dB) con una frecuencia de 1 lectura por segundo, acompañada de coordenadas GPS para cada punto de medición.

Objetivos del análisis:

  1. Describir estadísticamente los niveles de ruido en cada zona.
  2. Visualizar la distribución espacial de las mediciones mediante mapas interactivos.
  3. Comparar el comportamiento del sonido entre ambas zonas.
  4. Evaluar si los niveles registrados superan los umbrales recomendados por la OMS.

🔔 Referencia OMS: La Organización Mundial de la Salud recomienda que los niveles de ruido en entornos educativos no superen los 55 dB durante el día para no afectar la salud auditiva ni el rendimiento cognitivo.


2 Metodología

2.1 Instrumentación y recolección de datos

Las mediciones se realizaron con el micrófono integrado del teléfono (sensor Phone Microphone, paquete Builtin), que registra el nivel de sonido en decibeles. Cada registro corresponde a una lectura tomada cada segundo a lo largo de un recorrido a pie por cada zona del campus, el día 10 de febrero de 2026.

2.2 Variables registradas

Variable Tipo Descripción
ObjectID Numérica Identificador único de cada medición
Session_Name Texto Zona de medición (Ciencias / Licenciatura)
Timestamp Fecha-hora Fecha y hora exacta de la medición
Latitude Numérica Latitud GPS del punto
Longitude Numérica Longitud GPS del punto
X1.Measurement_Value Numérica Nivel de sonido en decibeles (dB)

2.3 Herramientas utilizadas

El análisis completo fue desarrollado en R con los siguientes paquetes:

Paquete Uso principal
dplyr, tidyr Manipulación y transformación de datos
ggplot2 Visualización estadística
leaflet Mapas interactivos con puntos GPS
rcartocolor Paletas de color CartoCOLORS (TealGrn, PurpOr)
kableExtra Tablas formateadas en HTML
lubridate Manejo de fechas y horas
scales Formateo de ejes y etiquetas

3 Carga y preparación de datos

3.1 Instalación y carga de paquetes

En R, antes de usar cualquier función especializada es necesario cargar el paquete que la contiene. El siguiente bloque verifica si cada paquete está instalado y, de no estarlo, lo instala automáticamente antes de cargarlo:

paquetes <- c("dplyr", "ggplot2", "leaflet", "kableExtra",
              "lubridate", "tidyr", "scales", "rcartocolor")

for (p in paquetes) {
  if (!require(p, character.only = TRUE, quietly = TRUE)) {
    install.packages(p, quiet = TRUE)
    library(p, character.only = TRUE)
  }
}

3.2 Lectura de archivos CSV

Los archivos exportados por la aplicación de medición contienen 8 filas de metadatos del sensor (nombre del dispositivo, tipo de medición, unidades, etc.) antes de los datos reales. El parámetro skip = 8 permite omitirlas y leer directamente la tabla:

ciencias     <- read.csv("C:/Users/rizek/Downloads/Rdatos/ciencias.csv",     skip = 8)
licenciatura <- read.csv("C:/Users/rizek/Downloads/Rdatos/licenciatura.csv", skip = 8)

cat("Registros cargados - Ciencias:     ", nrow(ciencias), "\n")
## Registros cargados - Ciencias:      1164
cat("Registros cargados - Licenciatura: ", nrow(licenciatura), "\n")
## Registros cargados - Licenciatura:  1194

3.3 Limpieza y estandarización

Para trabajar cómodamente con los datos es necesario: renombrar las columnas a nombres más claros, convertir el campo de fecha/hora a un formato que R pueda interpretar con lubridate, y eliminar filas con valores nulos o incorrectos:

preparar_datos <- function(df, zona) {
  df %>%
    rename(
      id        = ObjectID,
      sesion    = Session_Name,
      timestamp = Timestamp,
      lat       = Latitude,
      lon       = Longitude,
      db        = X1.Measurement_Value
    ) %>%
    mutate(
      zona      = zona,
      # ymd_hms() convierte el texto "2026-02-10T15:13:27" a objeto fecha-hora
      timestamp = ymd_hms(timestamp),
      # Número de segundo dentro del recorrido (útil para la serie de tiempo)
      segundo   = row_number(),
      # Truncar al minuto para promedios agrupados
      minuto    = floor_date(timestamp, "min")
    ) %>%
    # Eliminar registros con dB nulo o igual a cero (errores del sensor)
    filter(!is.na(db), db > 0)
}

ciencias     <- preparar_datos(ciencias,     "Ciencias")
licenciatura <- preparar_datos(licenciatura, "Licenciatura")

# Combinar ambos datasets en uno solo para análisis comparativos
datos <- bind_rows(ciencias, licenciatura) %>%
  mutate(zona = factor(zona, levels = c("Ciencias", "Licenciatura")))

cat("Total de registros combinados:", nrow(datos), "\n")
## Total de registros combinados: 2358

3.4 Vista previa de los datos limpios

head(datos, 10)
id sesion timestamp lat lon db zona segundo minuto
1 Ciencias 2026-02-10 15:13:27 3.375763 -76.53371 63.80528 Ciencias 1 2026-02-10 15:13:00
2 Ciencias 2026-02-10 15:13:28 3.375763 -76.53371 66.61991 Ciencias 2 2026-02-10 15:13:00
3 Ciencias 2026-02-10 15:13:29 3.375763 -76.53371 64.59090 Ciencias 3 2026-02-10 15:13:00
4 Ciencias 2026-02-10 15:13:30 3.375763 -76.53371 63.72378 Ciencias 4 2026-02-10 15:13:00
5 Ciencias 2026-02-10 15:13:31 3.375763 -76.53371 64.49533 Ciencias 5 2026-02-10 15:13:00
6 Ciencias 2026-02-10 15:13:32 3.375763 -76.53371 65.19057 Ciencias 6 2026-02-10 15:13:00
7 Ciencias 2026-02-10 15:13:33 3.375763 -76.53371 65.36375 Ciencias 7 2026-02-10 15:13:00
8 Ciencias 2026-02-10 15:13:34 3.375763 -76.53371 64.64674 Ciencias 8 2026-02-10 15:13:00
9 Ciencias 2026-02-10 15:13:35 3.375656 -76.53384 66.58007 Ciencias 9 2026-02-10 15:13:00
10 Ciencias 2026-02-10 15:13:36 3.375655 -76.53385 65.53665 Ciencias 10 2026-02-10 15:13:00

4 Estadísticas Descriptivas

Las estadísticas descriptivas permiten resumir numéricamente el comportamiento de una variable. Para el nivel de sonido son especialmente relevantes la media (nivel promedio), la desviación estándar (variabilidad) y los percentiles (distribución de los valores).

4.1 Resumen estadístico por zona

colores_zona <- c("Ciencias" = COL_CIENCIAS, "Licenciatura" = COL_LICENCIATURA)

resumen <- datos %>%
  group_by(zona) %>%
  summarise(
    N       = n(),
    Media   = round(mean(db), 2),
    Mediana = round(median(db), 2),
    Minimo  = round(min(db), 2),
    Maximo  = round(max(db), 2),
    DS      = round(sd(db), 2),
    CV_pct  = round((sd(db) / mean(db)) * 100, 1),
    P25     = round(quantile(db, 0.25), 2),
    P75     = round(quantile(db, 0.75), 2),
    .groups = "drop"
  )

resumen %>%
  kable(
    caption   = "Tabla 1. Estadísticas descriptivas del nivel de sonido (dB) por zona",
    col.names = c("Zona", "N", "Media (dB)", "Mediana (dB)", "Min (dB)",
                  "Max (dB)", "DS (dB)", "CV (%)", "P25", "P75")
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) %>%
  column_spec(1, bold = TRUE) %>%
  row_spec(1, color = COL_CIENCIAS) %>%
  row_spec(2, color = COL_LICENCIATURA)
Tabla 1. Estadísticas descriptivas del nivel de sonido (dB) por zona
Zona N Media (dB) Mediana (dB) Min (dB) Max (dB) DS (dB) CV (%) P25 P75
Ciencias 1164 66.09 65.69 54.08 82.64 4.98 7.5 62.29 69.51
Licenciatura 1194 70.84 70.73 57.00 85.32 4.99 7.1 67.16 74.43

Interpretación: La media indica el nivel sonoro típico del recorrido. La desviación estándar (DS) mide cuánto varían las lecturas: una DS alta sugiere un ambiente con picos pronunciados. El coeficiente de variación (CV) relativiza esa variabilidad respecto a la media, permitiendo comparar la homogeneidad del ruido entre zonas.

4.2 Comparación con el umbral OMS (55 dB)

proporcion <- datos %>%
  group_by(zona) %>%
  summarise(
    Total        = n(),
    Sobre_umbral = sum(db > UMBRAL_OMS),
    Pct_sobre    = round(Sobre_umbral / Total * 100, 1),
    .groups      = "drop"
  )

proporcion %>%
  kable(
    caption   = "Tabla 2. Mediciones que superan el umbral OMS de 55 dB",
    col.names = c("Zona", "Total mediciones", "Sobre 55 dB", "% sobre umbral")
  ) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  column_spec(4, bold = TRUE,
              color      = "white",
              background = c(COL_CIENCIAS, COL_LICENCIATURA))
Tabla 2. Mediciones que superan el umbral OMS de 55 dB
Zona Total mediciones Sobre 55 dB % sobre umbral
Ciencias 1164 1162 99.8
Licenciatura 1194 1194 100.0

Interpretación: Un porcentaje alto de mediciones sobre 55 dB indica que el ambiente supera con frecuencia el límite recomendado, lo que puede tener implicaciones para la salud auditiva y el rendimiento académico de quienes habitan esas zonas.


5 Visualización de Distribuciones

5.1 Histogramas por zona

El histograma muestra la frecuencia con que se repite cada rango de valores de dB. Permite identificar si los datos se concentran en valores bajos o altos, y si la distribución es simétrica o sesgada:

ggplot(datos, aes(x = db, fill = zona)) +
  geom_histogram(binwidth = 2, color = "white", alpha = 0.85) +
  geom_vline(xintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.8) +
  annotate("text", x = UMBRAL_OMS + 0.8, y = Inf,
           label = "Limite OMS (55 dB)", vjust = 2, hjust = 0,
           color = "#7b2d00", size = 3.5) +
  facet_wrap(~zona, ncol = 1) +
  scale_fill_manual(values = colores_zona) +
  scale_x_continuous(breaks = seq(40, 100, by = 5)) +
  labs(
    title    = "Distribucion de niveles de sonido por zona",
    subtitle = "Cada barra representa la cantidad de segundos en ese rango de dB",
    x        = "Nivel de sonido (dB)",
    y        = "Frecuencia (segundos)",
    caption  = "La linea discontinua indica el limite recomendado por la OMS (55 dB)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    plot.subtitle   = element_text(color = "gray50"),
    strip.text      = element_text(face = "bold", size = 12),
    legend.position = "none"
  )

5.2 Curva de densidad comparativa

La curva de densidad es una versión suavizada del histograma que facilita la comparación visual entre dos distribuciones en el mismo gráfico, mostrando qué valores son más probables en cada zona:

ggplot(datos, aes(x = db, fill = zona, color = zona)) +
  geom_density(alpha = 0.35, linewidth = 1) +
  geom_vline(xintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.8) +
  annotate("text", x = UMBRAL_OMS + 0.5, y = Inf,
           label = "OMS 55 dB", vjust = 2, hjust = 0,
           color = "#7b2d00", size = 3.5) +
  scale_fill_manual(values  = colores_zona) +
  scale_color_manual(values = colores_zona) +
  labs(
    title    = "Densidad de probabilidad del nivel sonoro",
    subtitle = "Comparacion entre zonas del campus",
    x        = "Nivel de sonido (dB)",
    y        = "Densidad",
    fill     = "Zona", color = "Zona"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    plot.subtitle   = element_text(color = "gray50"),
    legend.position = "bottom"
  )

5.3 Diagrama de caja (Boxplot)

El boxplot resume la distribución en cinco números clave: mínimo, primer cuartil (P25), mediana, tercer cuartil (P75) y máximo. Los puntos fuera de los bigotes son valores atípicos — momentos de ruido excepcionalmente alto o bajo:

ggplot(datos, aes(x = zona, y = db, fill = zona)) +
  geom_boxplot(alpha = 0.75, outlier.color = "gray40",
               outlier.size = 1, linewidth = 0.6) +
  geom_hline(yintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.8) +
  annotate("text", x = 0.55, y = UMBRAL_OMS + 1.5,
           label = "OMS 55 dB", hjust = 0, color = "#7b2d00", size = 3.5) +
  scale_fill_manual(values = colores_zona) +
  labs(
    title = "Distribucion del nivel sonoro por zona",
    x     = NULL,
    y     = "Nivel de sonido (dB)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    legend.position = "none"
  )

Interpretación: Una caja desplazada hacia arriba indica que la mayoría de las mediciones fueron altas. Los bigotes largos sugieren alta variabilidad. Los puntos atípicos señalan momentos puntuales de ruido inusual (un vehículo, una conversación cercana, etc.).


6 Serie de Tiempo

La serie de tiempo grafica la evolución del nivel de sonido segundo a segundo durante el recorrido. Permite identificar patrones temporales: ¿el ruido sube al cruzar una calle?, ¿hay momentos de menor intensidad entre edificios?

ggplot(datos, aes(x = segundo, y = db, color = zona)) +
  geom_line(alpha = 0.45, linewidth = 0.35) +
  geom_smooth(method = "loess", span = 0.15,
              se = TRUE, linewidth = 1.2, alpha = 0.2) +
  geom_hline(yintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.7) +
  annotate("text", x = 5, y = UMBRAL_OMS + 2,
           label = "OMS 55 dB", hjust = 0, color = "#7b2d00", size = 3.2) +
  facet_wrap(~zona, ncol = 1, scales = "free_x") +
  scale_color_manual(values = colores_zona) +
  scale_x_continuous(labels = function(x) paste0(x, "s")) +
  labs(
    title    = "Evolucion del nivel de sonido durante el recorrido",
    subtitle = "Linea delgada: lectura real | Banda: tendencia suavizada (LOESS)",
    x        = "Segundo del recorrido",
    y        = "Nivel de sonido (dB)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    plot.subtitle   = element_text(color = "gray50", size = 10),
    strip.text      = element_text(face = "bold"),
    legend.position = "none"
  )

Interpretación: La línea delgada muestra las fluctuaciones reales de dB segundo a segundo. La banda suavizada (método LOESS) revela la tendencia general del recorrido, eliminando el ruido aleatorio puntual. Los picos sostenidos en el tiempo son especialmente relevantes para la evaluación de exposición al ruido.


7 Análisis Espacial – Mapas Interactivos

El análisis espacial permite visualizar dónde dentro del campus se registraron los niveles más altos de ruido. Cada punto en el mapa corresponde a una medición GPS, coloreado según su nivel en dB. Los mapas son interactivos: puedes hacer zoom y clic sobre cada punto para ver los detalles.

7.1 Mapa – Zona Ciencias

pal_c <- colorNumeric(
  palette = rcartocolor::carto_pal(7, "TealGrn"),
  domain  = ciencias$db
)

leaflet(ciencias) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addCircleMarkers(
    lng         = ~lon, lat = ~lat,
    radius      = 5,
    fillColor   = ~pal_c(db),
    color       = ~pal_c(db),
    fillOpacity = 0.85,
    stroke      = FALSE,
    popup       = ~paste0(
      "<b>dB:</b> ", round(db, 1), "<br>",
      "<b>Hora:</b> ", format(timestamp, "%H:%M:%S"), "<br>",
      "<b>Zona:</b> Ciencias"
    )
  ) %>%
  addLegend("bottomright", pal = pal_c, values = ~db,
            title = "Nivel (dB)", opacity = 0.9)

7.2 Mapa – Zona Licenciatura

pal_l <- colorNumeric(
  palette = rcartocolor::carto_pal(7, "Purp"),
  domain  = licenciatura$db
)

leaflet(licenciatura) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addCircleMarkers(
    lng         = ~lon, lat = ~lat,
    radius      = 5,
    fillColor   = ~pal_l(db),
    color       = ~pal_l(db),
    fillOpacity = 0.85,
    stroke      = FALSE,
    popup       = ~paste0(
      "<b>dB:</b> ", round(db, 1), "<br>",
      "<b>Hora:</b> ", format(timestamp, "%H:%M:%S"), "<br>",
      "<b>Zona:</b> Licenciatura"
    )
  ) %>%
  addLegend("bottomright", pal = pal_l, values = ~db,
            title = "Nivel (dB)", opacity = 0.9)

7.3 Mapa comparativo (ambas zonas)

pal_zonas <- colorFactor(
  palette = c(COL_CIENCIAS, COL_LICENCIATURA),
  domain  = datos$zona
)

leaflet(datos) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addCircleMarkers(
    lng         = ~lon, lat = ~lat,
    radius      = 4,
    fillColor   = ~pal_zonas(zona),
    color       = ~pal_zonas(zona),
    fillOpacity = 0.75,
    stroke      = FALSE,
    popup       = ~paste0(
      "<b>Zona:</b> ", zona, "<br>",
      "<b>dB:</b> ", round(db, 1), "<br>",
      "<b>Hora:</b> ", format(timestamp, "%H:%M:%S")
    )
  ) %>%
  addLegend("bottomright", pal = pal_zonas, values = ~zona,
            title = "Zona", opacity = 0.9)

8 Comparación entre Zonas

8.1 Gráfica de violín

El gráfico de violín combina el boxplot con la curva de densidad: el ancho del violín en cada punto indica la frecuencia relativa de ese nivel de dB. Es especialmente útil para comparar la forma completa de dos distribuciones simultáneamente:

ggplot(datos, aes(x = zona, y = db, fill = zona)) +
  geom_violin(trim = FALSE, alpha = 0.7, linewidth = 0.5) +
  geom_boxplot(width = 0.08, fill = "white",
               outlier.shape = NA, linewidth = 0.6) +
  geom_hline(yintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.8) +
  annotate("text", x = 0.55, y = UMBRAL_OMS + 1.5,
           label = "OMS 55 dB", hjust = 0, color = "#7b2d00", size = 3.5) +
  scale_fill_manual(values = colores_zona) +
  labs(
    title    = "Comparacion de la distribucion sonora entre zonas",
    subtitle = "El ancho del violin indica la frecuencia relativa de cada nivel de dB",
    x        = NULL,
    y        = "Nivel de sonido (dB)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    plot.subtitle   = element_text(color = "gray50"),
    legend.position = "none"
  )

8.2 Evolución por minuto

Esta gráfica agrega las lecturas por minuto, lo que suaviza las fluctuaciones y permite comparar la tendencia general entre zonas a lo largo del tiempo de medición:

por_minuto <- datos %>%
  group_by(zona, minuto) %>%
  summarise(media_db = mean(db), .groups = "drop") %>%
  group_by(zona) %>%
  mutate(min_recorrido = row_number())

ggplot(por_minuto, aes(x = min_recorrido, y = media_db,
                       color = zona, group = zona)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2.5, alpha = 0.8) +
  geom_hline(yintercept = UMBRAL_OMS, linetype = "dashed",
             color = "#7b2d00", linewidth = 0.7) +
  scale_color_manual(values = colores_zona) +
  labs(
    title    = "Media de dB por minuto durante el recorrido",
    subtitle = "Promedio de todas las lecturas de cada minuto",
    x        = "Minuto del recorrido",
    y        = "Media dB",
    color    = "Zona"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(color = "#0d6b6e", face = "bold"),
    plot.subtitle   = element_text(color = "gray50"),
    legend.position = "bottom"
  )


9 Discusión de Resultados

Con base en los análisis realizados, se pueden extraer las siguientes observaciones:

Sobre los niveles generales: Los niveles de sonido registrados en ambas zonas superan frecuentemente el umbral de 55 dB recomendado por la OMS para entornos educativos, lo que sugiere condiciones acústicas que podrían afectar la concentración y el bienestar de estudiantes y docentes.

Sobre las diferencias entre zonas: La comparación estadística y visual entre Ciencias y Licenciatura revela diferencias en los niveles promedio y en la variabilidad del ruido. Estas diferencias pueden atribuirse a factores como el tráfico vehicular cercano, la densidad de personas, la actividad propia de cada facultad, o la configuración arquitectónica de cada zona.

Sobre la variabilidad temporal: La serie de tiempo evidencia que el nivel de ruido no es constante — existen picos asociados posiblemente a eventos puntuales (vehículos, grupos de personas) y momentos de menor intensidad entre edificios o en corredores.

Sobre la distribución espacial: Los mapas interactivos permiten identificar puntos de mayor ruido dentro de cada zona, información valiosa para proponer medidas de mitigación acústica focalizadas en los lugares más críticos.


10 Conclusiones

Este informe aplicó técnicas de analítica de datos ambientales para estudiar el ruido en dos zonas del campus universitario. Las principales conclusiones son:

  1. Ambas zonas presentan niveles de ruido elevados, con una proporción significativa de mediciones por encima del umbral recomendado por la OMS.
  2. Existen diferencias entre las zonas tanto en el nivel promedio como en la variabilidad, lo que refleja condiciones acústicas distintas.
  3. El análisis espacial con GPS permitió identificar con precisión los puntos de mayor ruido dentro de cada recorrido.
  4. El uso de R y R Markdown facilitó el procesamiento, visualización y comunicación de los datos de forma reproducible y documentada, integrando código, resultados y texto en un solo informe.

Como trabajo futuro se recomienda ampliar el período de medición para capturar variaciones a distintas horas del día, incluir más zonas del campus, y correlacionar los niveles de ruido con datos de afluencia estudiantil.



11 Referencias

Datos y herramienta de medición

Normativa y salud ambiental

Paquetes de R utilizados


Informe generado con R Markdown · Datos recolectados el 10 de febrero de 2026 · Campus universitario, Colombia