1. Introducción: Datos Crudos vs. Matriz de Datos

¿Qué son los datos crudos?

Los datos crudos son las mediciones y observaciones originales tal como se recopilaron en el campo o laboratorio. En nuestro caso, tenemos datos de evaluación de un sendero que incluyen mediciones de longitud, ancho, pendiente, y observaciones sobre obstáculos.

¿Qué es una matriz de datos?

Una matriz de datos es la organización estructurada de los datos crudos en formato tabular para análisis estadístico, donde:

  • Filas = casos únicos (cada medición del sendero)
  • Columnas = variables (longitud, ancho, pendiente, etc.)

2. Recomendaciones para Nombres de Variables en R

Para un análisis eficiente en R, los nombres de variables deben seguir estas reglas:

  • Minúsculas: trail_length en lugar de Trail Length
  • Sin espacios: usar _ o . como separadores
  • Sin caracteres especiales: evitar %, (), #
  • Descriptivos pero concisos: cross_slope en lugar de cs
  • Consistentes: mismo estilo en todo el dataset

3. Cargando las Librerías Necesarias

# Cargar librerías necesarias
library(readxl)      # Para leer archivos Excel
library(janitor)     # Para limpiar nombres de variables
library(tidyverse)  # Para manipulación y visualización de datos
library(dplyr)       # Para manipulación de datos
library(ggplot2)     # Para visualización
library(knitr)       # Para tablas
library(DT)          # Para tablas interactivas

4. Carga de Datos desde Excel y .csv

# Leer el archivo Excel
# Nota: Ajustar la ruta del archivo según corresponda
datos_crudos_x <- read_excel("datos_trail.xlsx", 
                          sheet = "Sheet1")

# Mostrar las primeras filas de los datos crudos
head(datos_crudos_x)
## # A tibble: 6 × 8
##   `Measurement #` `Trail length (m)` Walkable tread width (i…¹ `Cross slope (%)`
##             <dbl>              <dbl>                     <dbl>             <dbl>
## 1               1                0                          88               4.1
## 2               2                5                          65               2.4
## 3               3               10                          71               2.3
## 4               4               15.0                        70               3.7
## 5               5               20                          64               5.2
## 6               6               23                          62               1.7
## # ℹ abbreviated name: ¹​`Walkable tread width (in)`
## # ℹ 4 more variables: `Grade (%)` <dbl>,
## #   `Tread obstacles (0= no, 1=yes)` <dbl>, `Type of obstacle` <chr>,
## #   Observations <chr>
# ler datos desde archivo .csv
datos_crudos_c <- read.csv("datos_trail.csv")
# Mostrar las primeras filas de los datos crudos
head(datos_crudos_c)
##   Measurement.. Trail.length..m. Walkable.tread.width..in. Cross.slope....
## 1             1             0.00                        88             4.1
## 2             2             5.00                        65             2.4
## 3             3            10.00                        71             2.3
## 4             4            15.01                        70             3.7
## 5             5            20.00                        64             5.2
## 6             6            23.00                        62             1.7
##   Grade.... Tread.obstacles..0..no..1.yes. Type.of.obstacle   Observations
## 1       3.5                              0                  Start of trail
## 2       0.9                              0                                
## 3       8.3                              0                                
## 4      12.0                              1            Roots               
## 5      13.4                              1            Roots               
## 6      17.3                              0

Problemas con los nombres originales

# Examinar los nombres de columnas originales
cat("Nombres de columnas originales:\n")
## Nombres de columnas originales:
names(datos_crudos_x)
## [1] "Measurement #"                  "Trail length (m)"              
## [3] "Walkable tread width (in)"      "Cross slope (%)"               
## [5] "Grade (%)"                      "Tread obstacles (0= no, 1=yes)"
## [7] "Type of obstacle"               "Observations"

Los nombres originales tienen varios problemas: - Espacios en blanco - Caracteres especiales como %, (), # - Inconsistencias en formato

5. Uso de Janitor para Limpiar Nombres

# Usar janitor para limpiar nombres de variables
datos <- datos_crudos_x %>%
  clean_names()

# Mostrar nombres limpiados
cat("Nombres de columnas después de clean_names():\n")
## Nombres de columnas después de clean_names():
names(datos)
## [1] "measurement_number"         "trail_length_m"            
## [3] "walkable_tread_width_in"    "cross_slope_percent"       
## [5] "grade_percent"              "tread_obstacles_0_no_1_yes"
## [7] "type_of_obstacle"           "observations"

Renombrar variables para mayor claridad

# Renombrar algunas variables para mayor claridad
datos <- datos %>%
  rename(
    medicion = measurement_number,
    longitud_sendero_m = trail_length_m,
    ancho_transitable_in = walkable_tread_width_in,
    pendiente_transversal_pct = cross_slope_percent,
    pendiente_grado_pct = grade_percent,
    obstaculos_binario = tread_obstacles_0_no_1_yes,
    tipo_obstaculo = type_of_obstacle,
    observaciones = observations,
  )

# Verificar los nuevos nombres
names(datos)
## [1] "medicion"                  "longitud_sendero_m"       
## [3] "ancho_transitable_in"      "pendiente_transversal_pct"
## [5] "pendiente_grado_pct"       "obstaculos_binario"       
## [7] "tipo_obstaculo"            "observaciones"

6. Verificación de Estructura y Tipos de Datos

# Usar str() para examinar la estructura
str(datos)
## tibble [137 × 8] (S3: tbl_df/tbl/data.frame)
##  $ medicion                 : num [1:137] 1 2 3 4 5 6 7 8 9 10 ...
##  $ longitud_sendero_m       : num [1:137] 0 5 10 15 20 ...
##  $ ancho_transitable_in     : num [1:137] 88 65 71 70 64 62 60 75 72 63 ...
##  $ pendiente_transversal_pct: num [1:137] 4.1 2.4 2.3 3.7 5.2 1.7 7.3 3.4 3.8 3.1 ...
##  $ pendiente_grado_pct      : num [1:137] 3.5 0.9 8.3 12 13.4 ...
##  $ obstaculos_binario       : num [1:137] 0 0 0 1 1 0 0 1 0 0 ...
##  $ tipo_obstaculo           : chr [1:137] NA NA NA "Roots" ...
##  $ observaciones            : chr [1:137] "Start of trail" NA NA NA ...

7. Verificación de Datos Numéricos (Máximo y Mínimo)

# Seleccionar solo variables numéricas
variables_numericas <- datos %>%
  select_if(is.numeric)

# Resumen de variables numéricas
summary(variables_numericas)
##     medicion   longitud_sendero_m ancho_transitable_in
##  Min.   :  1   Min.   :  0.0      Min.   :  0.00      
##  1st Qu.: 35   1st Qu.:150.3      1st Qu.: 17.00      
##  Median : 69   Median :340.2      Median : 41.00      
##  Mean   : 69   Mean   :332.5      Mean   : 40.16      
##  3rd Qu.:103   3rd Qu.:510.3      3rd Qu.: 62.00      
##  Max.   :137   Max.   :630.5      Max.   :120.00      
##  pendiente_transversal_pct pendiente_grado_pct obstaculos_binario
##  Min.   : 0.000            Min.   : 0.000      Min.   :0.0000    
##  1st Qu.: 1.700            1st Qu.: 2.700      1st Qu.:0.0000    
##  Median : 3.600            Median : 6.300      Median :0.0000    
##  Mean   : 3.837            Mean   : 7.068      Mean   :0.4672    
##  3rd Qu.: 5.700            3rd Qu.:10.500      3rd Qu.:1.0000    
##  Max.   :11.300            Max.   :23.800      Max.   :1.0000

8. Verificación de Datos Categóricos con table()

# Verificar la variable de obstáculos (binaria)
cat("Distribución de obstáculos en el sendero:\n")
## Distribución de obstáculos en el sendero:
table(datos$obstaculos_binario, useNA = "ifany")
## 
##  0  1 
## 73 64
# Verificar tipos de obstáculos
cat("\nTipos de obstáculos encontrados:\n")
## 
## Tipos de obstáculos encontrados:
table(datos$tipo_obstaculo, useNA = "ifany")
## 
##          Pipe         Rocks Rocks + Roots          Root         Roots 
##             3            36             3             1            12 
##  Roots + Pipe          Step          <NA> 
##             2             7            73

9. Verificación de Valores Faltantes (NA)

# Contar NAs por columna
na_count <- datos %>%
  ungroup() %>%  # <--- Add this line
  summarise_all(~sum(is.na(.))) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "NAs") %>%
  arrange(desc(NAs))


na_count %>% 
  kable(caption = "Cantidad de valores faltantes por variable")
Cantidad de valores faltantes por variable
Variable NAs
observaciones 119
tipo_obstaculo 73
medicion 0
longitud_sendero_m 0
ancho_transitable_in 0
pendiente_transversal_pct 0
pendiente_grado_pct 0
obstaculos_binario 0

10. Conversión de Variables a Factores

# Identificar variables que deberían ser factores
datos_clean <- datos %>%
  mutate(
    # Convertir obstáculos binario a factor
    obstaculos_factor = factor(obstaculos_binario, 
                             levels = c(0, 1), 
                             labels = c("Sin obstáculo", "Con obstáculo")),
    
    # Convertir tipo de obstáculo a factor
    tipo_obstaculo_factor = factor(tipo_obstaculo),
    
    # Crear categorías de pendiente
    categoria_pendiente = case_when(
      pendiente_grado_pct < 5 ~ "Suave (< 5%)",
      pendiente_grado_pct >= 5 & pendiente_grado_pct < 15 ~ "Moderada (5-15%)",
      pendiente_grado_pct >= 15 ~ "Pronunciada (≥ 15%)"
    ),
    categoria_pendiente = factor(categoria_pendiente, 
                               levels = c("Suave (< 5%)", "Moderada (5-15%)", "Pronunciada (≥ 15%)")),
    
    # Crear categorías de ancho
    categoria_ancho = case_when(
      ancho_transitable_in < 30 ~ "Estrecho (< 30 in)",
      ancho_transitable_in >= 30 & ancho_transitable_in < 60 ~ "Medio (30-60 in)",
      ancho_transitable_in >= 60 ~ "Amplio (≥ 60 in)"
    ),
    categoria_ancho = factor(categoria_ancho,
                           levels = c("Estrecho (< 30 in)", "Medio (30-60 in)", "Amplio (≥ 60 in)"))
  )

# Verificar las nuevas variables categóricas
cat("Distribución de categorías de pendiente:\n")
## Distribución de categorías de pendiente:
table(datos_clean$categoria_pendiente, useNA = "ifany")
## 
##        Suave (< 5%)    Moderada (5-15%) Pronunciada (≥ 15%) 
##                  55                  71                  11
cat("\nDistribución de categorías de ancho:\n")
## 
## Distribución de categorías de ancho:
table(datos_clean$categoria_ancho, useNA = "ifany")
## 
## Estrecho (< 30 in)   Medio (30-60 in)   Amplio (≥ 60 in) 
##                 51                 48                 38