← Volver al Inicio
Universidad Nacional de Costa Rica

EIY403

Introducción al Análisis de Datos para Otras Carreras

Clase 2: Análisis Exploratorio de Datos (EDA)
II Semestre 2025
Escuela de Informática y Computación
Análisis Exploratorio de Datos
1 / 18
Universidad Nacional de Costa Rica

Agenda de la Clase

Bloque 1: EDA Profundo

  • Definición y objetivos del EDA
  • Proceso completo paso a paso
  • Buenas prácticas en cada fase
  • Decisiones críticas en limpieza

Bloque 2: Tipos de Datos

  • Clasificación detallada
  • Implicaciones para el análisis
  • Transformaciones necesarias

Bloque 3: Visualización

  • Cuándo usar cada gráfico
  • Histogramas vs barras
  • Pictogramas y polígonos
  • Errores comunes en visualización

Bloque 4: Estructuras de Control

  • If/else para análisis de datos
  • Bucles en procesamiento
  • Casos de uso prácticos
2 / 18
Universidad Nacional de Costa Rica

¿Qué es el análisis exploratorio de datos?

"El EDA es el proceso de investigar datos para descubrir lo desconocido, cuestionar lo asumido, y revelar patrones ocultos antes de aplicar modelos formales"

Objetivos Fundamentales

  • Comprensión: Entender qué dicen realmente los datos
  • Validación: Verificar la calidad e integridad
  • Descubrimiento: Encontrar patrones inesperados
  • Preparación: Limpiar y preparar para análisis
  • Comunicación: Visualizar hallazgos clave

Filosofía del EDA

  • Los datos tienen historias que contar
  • Nuestras suposiciones pueden estar equivocadas
  • La visualización revela más que los números
  • La calidad de los datos determina la calidad del análisis

Lo que NO es EDA

  • NO es solo hacer gráficos bonitos
  • NO es calcular estadísticas básicas
  • NO es un paso opcional
  • NO es algo que se hace una sola vez

Importancia Crítica

  • 80% del tiempo en ciencia de datos se gasta en EDA
  • Previene errores costosos en el análisis
  • Genera hipótesis para investigación futura
  • Mejora la comunicación de resultados
3 / 18
Universidad Nacional de Costa Rica

Proceso EDA: Los 6 pasos fundamentales

1
Inspección Inicial

Tamaño, estructura, tipos de variables, primeras 10 filas

2
Evaluación de Calidad

Valores faltantes, duplicados, outliers, inconsistencias

3
Limpieza Inteligente

Decisiones sobre missing data, duplicados, transformaciones

4
Análisis Univariado

Distribuciones, estadísticas descriptivas por variable

5
Análisis Bivariado

Correlaciones, relaciones entre variables

6
Síntesis y Hallazgos

Patrones identificados, hipótesis generadas

⚡ Regla de Oro del EDA

"Siempre visualiza antes de calcular, siempre cuestiona antes de asumir"

4 / 18
Universidad Nacional de Costa Rica

Evaluación de calidad: ¿Qué buscar?

Dimensiones de Calidad

  • Completitud: ¿Faltan datos?
  • Precisión: ¿Los valores son correctos?
  • Consistencia: ¿Formato uniforme?
  • Validez: ¿Valores dentro de rangos esperados?
  • Unicidad: ¿Hay duplicados?
  • Actualidad: ¿Los datos están vigentes?

Señales de Alerta

  • Valores imposibles (edad: -5, 150)
  • Formatos inconsistentes (fechas, números)
  • Códigos sin explicación
  • Distribuciones muy extrañas
  • Correlaciones perfectas sospechosas

Herramientas de Evaluación en R

# Evaluación inicial de los datos
str(datos)              # Estructura del dataframe
head(datos)             # Primeras 6 filas
tail(datos)             # Últimas 6 filas
dim(datos)              # Dimensiones (filas x columnas)

# Resumen estadístico
summary(datos)          # Estadísticas descriptivas

# Evaluación de calidad
sum(is.na(datos))       # Total de valores faltantes
colSums(is.na(datos))   # Valores faltantes por columna
sum(duplicated(datos))  # Filas completamente duplicadas

# Valores únicos
sapply(datos, function(x) length(unique(x)))

# Variables categóricas
table(datos$variable_categorica)  # Frecuencias

Preguntas Críticas

  • ¿De dónde vienen estos datos?
  • ¿Cómo fueron recolectados?
  • ¿Qué representan realmente las variables?
  • ¿Hay sesgos en la recolección?
  • ¿Los datos son representativos?
5 / 18
Universidad Nacional de Costa Rica

Decisiones críticas en limpieza

Estrategias para Datos Faltantes

Eliminar (Listwise deletion)

Cuándo usarlo:

  • < 5% de datos faltantes
  • Datos faltantes completamente aleatorios
  • Dataset muy grande

Imputar con medidas centrales

Media: Para datos numéricos simétricos

Mediana: Para datos asimétricos

Moda: Para datos categóricos

Imputación avanzada

  • Regresión lineal
  • K-nearest neighbors
  • Métodos basados en modelos

Estrategias para duplicados

Identificación

  • Duplicados exactos: Todas las columnas iguales
  • Duplicados parciales: ID iguales, otros datos diferentes
  • Duplicados conceptuales: Misma entidad, diferentes representaciones

Decisiones de acción

  • Eliminar automáticamente: Duplicados exactos
  • Revisar manualmente: Duplicados parciales
  • Crear reglas: Para duplicados conceptuales
  • Conservar el más reciente: Cuando hay timestamps

Outliers: ¿Eliminar o conservar?

CUIDADO: Los outliers pueden ser:

  • Errores de captura (eliminar)
  • Fenómenos raros pero reales (conservar)
  • Indicadores de problemas sistémicos
6 / 18
Universidad Nacional de Costa Rica

Tipos de datos: clasificación detallada

Datos cuantitativos

Discretos (Contables):

  • Número de estudiantes: 25, 30, 45
  • Cantidad de productos vendidos
  • Número de errores en código
  • Frecuencia de eventos

Continuos (Medibles):

  • Altura: 1.75m, 1.82m
  • Temperatura: 25.6°C
  • Tiempo de respuesta: 0.234s
  • Concentraciones químicas

Datos cualitativos

Nominales (Sin orden):

  • Color: rojo, azul, verde
  • Género: masculino, femenino, otro
  • Marca: Nike, Adidas, Puma
  • Tipo de reacción química

Ordinales (Con orden):

  • Satisfacción: muy bajo, bajo, medio, alto, muy alto
  • Nivel educativo: primaria, secundaria, universidad
  • Grado de pureza: baja, media, alta

Datos temporales

  • Fechas: 2025-08-05
  • Tiempo: 14:30:25
  • Duración: 2h 30min
  • Series temporales: Datos con timestamps

Datos geoespaciales

  • Coordenadas: Latitud/Longitud
  • Direcciones: Texto estructurado
  • Regiones: Países, provincias

Datos no estructurados

  • Texto: Comentarios, reviews, artículos
  • Imágenes: Fotos, gráficos, diagramas
  • Audio: Grabaciones, música
  • Video: Clips, presentaciones
  • JSON/XML: Datos semi-estructurados
Implicaciones para el análisis
  • Cuantitativos: Permiten operaciones matemáticas completas
  • Ordinales: Permiten ranking, pero no operaciones aritméticas
  • Nominales: Solo conteos y proporciones
  • Temporales: Permiten análisis de tendencias y estacionalidad
7 / 18
Universidad Nacional de Costa Rica

Escalas de medición: Qué operaciones permite cada una

Escala Características Operaciones Válidas Estadísticas Apropiadas Ejemplos
Nominal Solo clasificación
Sin orden natural
= ≠
Conteo
Frecuencias
Moda
Proporciones
Chi-cuadrado
Color, género, marca, tipo de reacción
Ordinal Clasificación + orden
Distancias no iguales
= ≠ < >
Ranking
Percentiles
Mediana
Cuartiles
Correlación de Spearman
Satisfacción, nivel educativo, grado de dolor
Intervalo Orden + distancias iguales
Sin cero absoluto
= ≠ < > + -
Diferencias
Promedios
Media
Desviación estándar
Correlación de Pearson
Temperatura en °C, IQ, fechas
Razón Intervalo + cero absoluto
Todas las propiedades
= ≠ < > + - × ÷
Ratios
Proporciones
Media geométrica
Coeficiente de variación
Todas las estadísticas
Altura, peso, ingresos, temperatura en Kelvin

Error Común: Aplicar estadísticas inapropiadas para el tipo de escala puede llevar a conclusiones incorrectas. Por ejemplo, calcular la media de satisfacción en escala Likert (ordinal) puede ser problemático.

8 / 18
Universidad Nacional de Costa Rica

Visualización: ¿Cuándo usar cada gráfico?

Histogramas

Cuándo usar:

  • Datos cuantitativos continuos
  • Mostrar distribución de frecuencias
  • Identificar forma de la distribución

Ejemplo: Distribución de edades, alturas, tiempos de respuesta

Buena práctica: Experimenta con diferentes números de bins (5-30 dependiendo del tamaño de datos)

Gráficos de barras

Cuándo usar:

  • Datos categóricos (nominales u ordinales)
  • Comparar frecuencias entre categorías
  • Mostrar conteos o proporciones

Ejemplo: Ventas por región, número de estudiantes por carrera

Evitar: Gráficos 3D innecesarios que distorsionan la percepción

Pictogramas

Cuándo usar:

  • Presentaciones públicas
  • Hacer datos más atractivos visualmente
  • Comunicar a audiencias no técnicas

Ejemplo: Población representada con figuras humanas

Cuidado: Pueden distorsionar proporciones si no se escalan correctamente

Polígonos de frecuencia

Cuándo usar:

  • Comparar distribuciones múltiples
  • Datos ordinales con muchas categorías
  • Mostrar tendencias en frecuencias

Ejemplo: Comparar distribuciones de calificaciones entre diferentes cursos

Ventaja: Más claro que múltiples histogramas superpuestos

9 / 18
Universidad Nacional de Costa Rica

Errores comunes en visualización

Errores técnicos

  • Ejes que no empiezan en cero: Exageran diferencias
  • Escalas inconsistentes: Entre gráficos comparativos
  • Bins inadecuados: Muy pocos o muchos en histogramas
  • Gráficos 3D innecesarios: Dificultan la lectura
  • Colores problemáticos: No accesibles para daltónicos

Tipo de gráfico incorrecto

  • Gráfico de líneas para categóricos: Implica continuidad falsa
  • Gráfico circular con >7 categorías: Difícil de leer
  • Barras para datos continuos: Pérdida de información
  • Boxplots para datos categóricos: Sin sentido estadístico

Buenas prácticas

  • Títulos descriptivos: Que expliquen qué se muestra
  • Etiquetas claras: En ejes y leyendas
  • Colores significativos: Que refuercen el mensaje
  • Simplicidad: Eliminar elementos innecesarios
  • Contexto: Incluir información relevante

Principios de diseño

  • Contraste: Elementos importantes deben destacar
  • Alineación: Elementos organizados visualmente
  • Repetición: Consistencia en estilo
  • Proximidad: Elementos relacionados juntos

Paletas de colores en R

# Paletas accesibles recomendadas en R
library(RColorBrewer)
library(viridis)

# Paletas para datos categóricos
RColorBrewer::display.brewer.all(colorblindFriendly = TRUE)
brewer.pal(8, "Set2")    # Colores suaves y distinguibles
brewer.pal(8, "Dark2")   # Colores más intensos

# Paletas para datos continuos
viridis(10)              # Paleta viridis (amarillo-verde-azul)
plasma(10)               # Paleta plasma (rosa-púrpura)
cividis(10)              # Diseñada específicamente para daltonismo

# Ejemplo de uso en ggplot2
ggplot(data) + 
  geom_point(aes(x = var1, y = var2, color = categoria)) +
  scale_color_brewer(type = "qual", palette = "Set2")

# EVITAR: combinaciones problemáticas
# - Rojo y verde juntos (daltonismo más común)
# - Colores muy similares en tonalidad
# - Más de 8-10 colores categóricos diferentes
10 / 18
Universidad Nacional de Costa Rica

Medidas de tendencia central: ¿Cuál elegir?

Media Aritmética ($\bar{x}$)

$$\bar{x} = \frac{\sum_{i=1}^{n} x_i}{n}$$

Usar cuando:

  • Distribución simétrica
  • Sin valores atípicos extremos
  • Datos de escala intervalo o razón
  • Se necesita precisión matemática

Evitar cuando:

  • Distribución muy asimétrica
  • Presencia de outliers
  • Datos ordinales
  • Datos con valores extremos influyentes

Ejemplo problemático: Ingresos familiares con algunos millonarios en la muestra → la media será engañosa

Mediana (Me) y Moda (Mo)

Mediana - El valor del medio:

  • Robusta ante outliers
  • Apropiada para datos ordinales
  • Mejor para distribuciones asimétricas
  • Interpretación clara: 50% por encima/debajo

Moda - El valor más frecuente:

  • Única medida para datos nominales
  • Identifica valores típicos/populares
  • Puede tener múltiples valores
  • Puede no existir o ser poco informativa

Regla práctica:

  • Simétrica: Media ≈ Mediana ≈ Moda
  • Asimétrica positiva: Media > Mediana > Moda
  • Asimétrica negativa: Media < Mediana < Moda
11 / 18
Universidad Nacional de Costa Rica

Medidas de tendencia no central

Cuartiles y Percentiles

$$Q_1 = P_{25}, \quad Q_2 = P_{50} = Me, \quad Q_3 = P_{75}$$

Interpretación:

  • Q1: 25% de datos por debajo
  • Q2: Mediana (50%)
  • Q3: 75% de datos por debajo
  • P90: 90% de datos por debajo

Rango Intercuartílico (IQR)

$$IQR = Q_3 - Q_1$$

Ventajas del IQR:

  • Robusto ante outliers
  • Describe el 50% central de los datos
  • Base para detectar outliers
  • Útil para comparar dispersión

Cálculo de Cuartiles en R

# Cálculo de cuartiles y percentiles
Q1 <- quantile(datos$variable, 0.25)    # Primer cuartil
Q2 <- quantile(datos$variable, 0.50)    # Mediana
Q3 <- quantile(datos$variable, 0.75)    # Tercer cuartil

# Percentiles específicos
P10 <- quantile(datos$variable, 0.10)   # Percentil 10
P90 <- quantile(datos$variable, 0.90)   # Percentil 90

# Resumen completo de cuartiles
summary(datos$variable)                 # Min, Q1, Median, Q3, Max

# Rango intercuartílico
IQR_valor <- IQR(datos$variable)        # Función directa
# O manualmente:
IQR_manual <- Q3 - Q1

Detección de Outliers con IQR

$$\text{Outlier inferior} < Q_1 - 1.5 \times IQR$$ $$\text{Outlier superior} > Q_3 + 1.5 \times IQR$$
# Detección de outliers usando IQR
Q1 <- quantile(datos$variable, 0.25)
Q3 <- quantile(datos$variable, 0.75)
IQR_val <- Q3 - Q1

# Definir límites
limite_inferior <- Q1 - 1.5 * IQR_val
limite_superior <- Q3 + 1.5 * IQR_val

# Identificar outliers
outliers <- datos[datos$variable < limite_inferior | 
                  datos$variable > limite_superior, ]

# Contar outliers
num_outliers <- nrow(outliers)
cat("Outliers encontrados:", num_outliers)

# Boxplot automático (muestra outliers)
boxplot(datos$variable, main = "Detección de Outliers")

Aplicaciones Prácticas

  • Educación: Percentiles en exámenes estandarizados
  • Medicina: Percentiles de crecimiento infantil
  • Química: Control de calidad en concentraciones
  • Agricultura: Análisis de rendimientos por parcela
12 / 18
Universidad Nacional de Costa Rica

Medidas de dispersión: ¿Qué tan dispersos están los datos?

Varianza y Desviación Estándar

$$\text{Varianza poblacional: } \sigma^2 = \frac{\sum(x_i - \mu)^2}{N}$$ $$\text{Varianza muestral: } s^2 = \frac{\sum(x_i - \bar{x})^2}{n-1}$$ $$\text{Desviación estándar: } s = \sqrt{s^2}$$

¿Por qué n-1 en la muestra?

  • Corrección de Bessel
  • Estimador insesgado de σ²
  • Perdemos 1 grado de libertad al estimar $\bar{x}$

Interpretación de la Desviación Estándar

Regla Empírica (distribución normal):

  • 68% de datos en $\bar{x} \pm 1s$
  • 95% de datos en $\bar{x} \pm 2s$
  • 99.7% de datos en $\bar{x} \pm 3s$

Coeficiente de Variación

$$CV = \frac{s}{\bar{x}} \times 100\%$$

Interpretación del CV:

  • CV < 15%: Baja variabilidad
  • 15% ≤ CV ≤ 30%: Variabilidad moderada
  • CV > 30%: Alta variabilidad

¿Cuándo usar CV?

  • Comparar variabilidad entre datasets con diferentes unidades
  • Comparar variabilidad cuando las medias son muy diferentes
  • Evaluar precisión de mediciones

Limitación: CV no es apropiado cuando la media es cercana a cero o puede ser negativa

Otras Medidas de Dispersión

  • Rango: Máximo - Mínimo (muy sensible a outliers)
  • MAD: Mediana de las desviaciones absolutas
  • Rango intercuartílico: Q3 - Q1 (robusto)
13 / 18
Universidad Nacional de Costa Rica

Estructuras de control para análisis de datos

"Las estructuras de control nos permiten tomar decisiones automáticas sobre nuestros datos y procesar grandes volúmenes de información de manera eficiente"
Estructuras Condicionales

if/else/elif: Tomar decisiones basadas en condiciones

Casos de uso en análisis:

  • Clasificar datos en categorías
  • Filtrar outliers
  • Aplicar transformaciones condicionales
  • Validar calidad de datos
  • Crear variables dummy
Estructuras Iterativas

for/while: Repetir operaciones múltiples veces

Casos de uso en análisis:

  • Procesar múltiples archivos
  • Aplicar análisis a subgrupos
  • Generar múltiples gráficos
  • Calcular estadísticas repetitivas
  • Imputar datos faltantes
¿Por qué son importantes en análisis de datos?
  • Automatización: Procesar miles de registros sin intervención manual
  • Consistencia: Aplicar las mismas reglas a todos los datos
  • Escalabilidad: El mismo código funciona para 100 o 100,000 registros
  • Reproducibilidad: Los mismos pasos se pueden repetir exactamente
14 / 18
Universidad Nacional de Costa Rica

Condicionales if/else: Casos prácticos

Sintaxis Básica en R

# Estructura básica
if (condicion) {
    accion1
} else if (otra_condicion) {
    accion2
} else {
    accion3
}

# Función ifelse() para vectores
resultado <- ifelse(condicion, valor_si_verdadero, valor_si_falso)

# ifelse() anidado
resultado <- ifelse(condicion1, "opcion1",
                   ifelse(condicion2, "opcion2", "opcion3"))

Ejemplo 1: Clasificación de Edades

# Función personalizada
clasificar_edad <- function(edad) {
    if (edad < 18) {
        return("Menor de edad")
    } else if (edad < 65) {
        return("Adulto")
    } else {
        return("Adulto mayor")
    }
}

# Aplicar a todo el dataset
datos$categoria_edad <- sapply(datos$edad, clasificar_edad)

# Alternativa con ifelse (más eficiente)
datos$categoria_edad <- ifelse(datos$edad < 18, "Menor de edad",
                              ifelse(datos$edad < 65, "Adulto", 
                                    "Adulto mayor"))

Ejemplo 2: Detección de Outliers

# Calcular límites IQR
Q1 <- quantile(datos$variable, 0.25)
Q3 <- quantile(datos$variable, 0.75)
IQR_val <- Q3 - Q1

# Función para clasificar valores
clasificar_outlier <- function(valor) {
    if (valor < Q1 - 1.5 * IQR_val) {
        return("Outlier inferior")
    } else if (valor > Q3 + 1.5 * IQR_val) {
        return("Outlier superior")
    } else {
        return("Normal")
    }
}

# Aplicar clasificación
datos$tipo_valor <- sapply(datos$variable, clasificar_outlier)

Ejemplo 3: Validación de Datos Químicos

# Validar concentraciones químicas (ppm)
validar_concentracion <- function(conc) {
    if (is.na(conc)) {
        return("Dato faltante")
    } else if (conc < 0) {
        return("Valor imposible")
    } else if (conc == 0) {
        return("Sin detectar")
    } else if (conc > 1000) {
        return("Concentración alta")
    } else {
        return("Normal")
    }
}

# Aplicar validación
datos$validez_conc <- sapply(datos$concentracion, validar_concentracion)

# Contar por categoría
table(datos$validez_conc)

Ejemplo 4: Imputación Inteligente

# Imputación basada en condiciones
imputar_ph <- function(row) {
    if (is.na(row["ph"])) {
        if (row["tipo_muestra"] == "agua_potable") {
            return(7.0)  # pH neutro típico
        } else if (row["tipo_muestra"] == "suelo_acido") {
            return(5.5)  # pH ácido típico
        } else {
            return(6.8)  # pH promedio general
        }
    } else {
        return(row["ph"])
    }
}

# Aplicar usando apply por filas
datos$ph_imputado <- apply(datos, 1, imputar_ph)

# Verificar imputación
sum(is.na(datos$ph))         # Antes
sum(is.na(datos$ph_imputado)) # Después

Consejos Prácticos

  • ifelse(): Más eficiente para vectores grandes
  • Funciones personalizadas: Mejor para lógica compleja
  • Validar datos: Siempre revisar casos extremos
  • Documentar: Comentar la lógica de decisiones
15 / 18
Universidad Nacional de Costa Rica

Bucles for/while: Automatización de procesos

Bucle for - Iteración Definida

# Procesar múltiples archivos de laboratorio
archivos <- list.files(pattern = "analisis_.*\\.csv")
lista_datos <- list()

for (i in 1:length(archivos)) {
    # Leer cada archivo
    datos_lab <- read.csv(archivos[i])
    
    # Agregar información de fuente
    datos_lab$archivo_origen <- archivos[i]
    datos_lab$fecha_procesado <- Sys.Date()
    
    # Guardar en lista
    lista_datos[[i]] <- datos_lab
}

# Combinar todos los datos
datos_completos <- do.call(rbind, lista_datos)
cat("Procesados", length(archivos), "archivos")
cat("Total de filas:", nrow(datos_completos))

Análisis por Grupos de Muestras

# Estadísticas por tipo de muestra química
tipos_muestra <- unique(datos$tipo_muestra)
resultados <- data.frame()

for (tipo in tipos_muestra) {
    # Filtrar por tipo
    subconjunto <- datos[datos$tipo_muestra == tipo, ]
    
    # Calcular estadísticas
    stats <- data.frame(
        tipo_muestra = tipo,
        n_muestras = nrow(subconjunto),
        ph_promedio = mean(subconjunto$ph, na.rm = TRUE),
        ph_desv_std = sd(subconjunto$ph, na.rm = TRUE),
        concentracion_max = max(subconjunto$concentracion, na.rm = TRUE)
    )
    
    # Agregar a resultados
    resultados <- rbind(resultados, stats)
}

# Ver resultados
print(resultados)

Generación Automática de Gráficos

# Crear histogramas para múltiples variables químicas
library(ggplot2)
variables_quimicas <- c("ph", "concentracion", "turbidez", "conductividad")

for (var in variables_quimicas) {
    # Crear gráfico
    p <- ggplot(datos, aes_string(x = var)) +
        geom_histogram(bins = 20, fill = "steelblue", alpha = 0.7) +
        labs(
            title = paste("Distribución de", var),
            x = var,
            y = "Frecuencia"
        ) +
        theme_minimal()
    
    # Guardar gráfico
    nombre_archivo <- paste0("histograma_", var, ".png")
    ggsave(nombre_archivo, p, width = 8, height = 6)
    
    cat("Gráfico guardado:", nombre_archivo, "\n")
}

# Crear boxplots por grupo
for (var in variables_quimicas) {
    p <- ggplot(datos, aes_string(x = "tipo_muestra", y = var)) +
        geom_boxplot(fill = "lightblue") +
        labs(title = paste("Boxplot de", var, "por tipo de muestra"))
    
    ggsave(paste0("boxplot_", var, ".png"), p)
}

Bucle while - Control de Calidad Iterativo

# Limpieza iterativa de outliers extremos
datos_limpios <- datos
outliers_encontrados <- TRUE
iteracion <- 0
max_iteraciones <- 5

while (outliers_encontrados && iteracion < max_iteraciones) {
    # Calcular límites IQR
    Q1 <- quantile(datos_limpios$concentracion, 0.25, na.rm = TRUE)
    Q3 <- quantile(datos_limpios$concentracion, 0.75, na.rm = TRUE)
    IQR_val <- Q3 - Q1
    
    # Detectar outliers extremos
    limite_inf <- Q1 - 3 * IQR_val  # Más estricto (3 x IQR)
    limite_sup <- Q3 + 3 * IQR_val
    
    outliers <- which(datos_limpios$concentracion < limite_inf | 
                      datos_limpios$concentracion > limite_sup)
    
    if (length(outliers) == 0) {
        outliers_encontrados <- FALSE
        cat("No se encontraron más outliers extremos\n")
    } else {
        # Remover outliers
        datos_limpios <- datos_limpios[-outliers, ]
        iteracion <- iteracion + 1
        cat("Iteración", iteracion, "- Removidos", length(outliers), "outliers\n")
    }
}

cat("Proceso completado en", iteracion, "iteraciones")
cat("Datos finales:", nrow(datos_limpios), "de", nrow(datos), "originales")
16 / 18
Universidad Nacional de Costa Rica

Mejores prácticas en estructuras de control

Buenas Prácticas

  • Legibilidad: Usa nombres descriptivos para variables
  • Documentación: Comenta el propósito de cada bucle
  • Validación: Verifica condiciones antes de procesar
  • Eficiencia: Evita bucles innecesarios
  • Modularidad: Divide tareas complejas en funciones

Optimización en R

#  Ineficiente - Bucle innecesario
resultado_lento <- c()
for (i in 1:nrow(datos)) {
    if (datos$ph[i] > 7) {
        resultado_lento <- c(resultado_lento, datos$muestra_id[i])
    }
}

#  Eficiente - Vectorización
resultado_rapido <- datos$muestra_id[datos$ph > 7]

#  Muy lento - Concatenar vectores en bucle
concentraciones_altas <- c()
for (i in 1:nrow(datos)) {
    if (datos$concentracion[i] > 100) {
        # ¡Esto recrea el vector cada vez!
        concentraciones_altas <- c(concentraciones_altas, datos$concentracion[i])
    }
}

#  Más eficiente - Pre-asignar espacio
indices_altas <- which(datos$concentracion > 100)
concentraciones_altas <- datos$concentracion[indices_altas]

🔧 Usar Funciones de la Familia apply

#  Bucle para calcular medias por grupo
grupos <- unique(datos$tipo_muestra)
medias_por_grupo <- numeric()

for (grupo in grupos) {
    subset_datos <- datos[datos$tipo_muestra == grupo, ]
    media_grupo <- mean(subset_datos$ph, na.rm = TRUE)
    medias_por_grupo <- c(medias_por_grupo, media_grupo)
}

#  Más eficiente con aggregate()
medias_por_grupo <- aggregate(ph ~ tipo_muestra, 
                             datos, mean, na.rm = TRUE)

#  O con tapply()
medias_tapply <- tapply(datos$ph, datos$tipo_muestra, 
                       mean, na.rm = TRUE)

Errores Comunes

  • Bucles infinitos: Olvidar actualizar la condición
  • Índices fuera de rango: No validar límites
  • Modificar durante iteración: Cambiar la estructura que se recorre
  • Concatenar vectores: Usar c() en bucles es muy lento
  • No usar vectorización: Bucles innecesarios

Validación y Manejo de Errores en R

# Validación robusta al procesar archivos
archivos_laboratorio <- list.files(pattern = "\\.csv$")

for (archivo in archivos_laboratorio) {
    # Verificar que el archivo existe
    if (file.exists(archivo)) {
        
        # Manejo de errores con tryCatch
        datos_archivo <- tryCatch({
            read.csv(archivo, stringsAsFactors = FALSE)
        }, error = function(e) {
            cat("Error leyendo", archivo, ":", e$message, "\n")
            return(NULL)
        })
        
        # Continuar solo si la lectura fue exitosa
        if (!is.null(datos_archivo)) {
            # Validar estructura esperada
            if (all(c("muestra_id", "ph", "concentracion") %in% names(datos_archivo))) {
                # Procesar datos...
                cat("Procesado exitosamente:", archivo, "\n")
            } else {
                cat("Columnas faltantes en", archivo, "\n")
            }
        }
    } else {
        cat("Archivo no encontrado:", archivo, "\n")
    }
}

Cuándo NO usar bucles en R

  • Operaciones vectorizadas: `+`, `-`, `*`, `/`, `>`, etc.
  • Funciones apply: `apply()`, `lapply()`, `sapply()`, `mapply()`
  • Agregaciones: `aggregate()`, `tapply()`, `by()`
  • Filtros y subsets: Indexación lógica directa
  • Transformaciones: `ifelse()`, `cut()`, `factor()`
17 / 18
Universidad Nacional de Costa Rica

Resumen y próxima clase

Lo que aprendimos hoy

  • EDA profundo: Proceso de 6 pasos sistemático
  • Calidad de datos: Cómo evaluarla y mejorarla
  • Decisiones inteligentes: En limpieza y preparación
  • Tipos de datos: Clasificación y sus implicaciones
  • Visualización efectiva: Cuándo usar cada gráfico
  • Estadísticas descriptivas: Cuándo usar cada medida
  • Estructuras de control: Automatización de análisis

Conceptos Clave

  • 80% del tiempo se invierte en preparar datos
  • La visualización revela patrones ocultos
  • No todas las estadísticas son apropiadas para todos los datos
  • La automatización hace escalable el análisis

Próxima Clase: Programación Práctica

  • Laboratorio #2: Sintaxis avanzada de R/Python
  • Estructuras de datos: listas, diccionarios, data frames
  • Importación de datos reales
  • Implementación práctica del proceso EDA
  • Primeras visualizaciones con código

Para la próxima clase

  • Tarea #2: Ejercicios de estructuras de control
  • Instalar/verificar software (Python/R + IDE)
  • Traer datos de su área disciplinaria (opcional)
  • Revisar tipos de archivos de datos (.csv, .xlsx)

Reflexión Final

"El EDA no es solo una fase previa al análisis, es la conversación inicial con nuestros datos. Entre mejor sea esta conversación, más reveladores serán los insights que obtengamos."

¡Gracias por su atención!

¿Preguntas sobre el proceso EDA o estructuras de control?

18 / 18