Unidad 3 - Visualización de Datos con ggplot2

Introducción al Business Analytics · Semana 5 · 06278-ECO

Autor/a

PhD. Eduard F. Martínez-González

1 Objetivo de la semana

Esta semana NO aprenderemos “sintaxis de gráficos” por sí misma. El foco está en comunicación, no en memorizar comandos.

¿Qué significa “comunicar con gráficos”?

Significa convertir tablas de KPIs (que ya sabemos construir con dplyr) en visualizaciones claras que transmitan insights y apoyen decisiones de negocio.

Un gráfico bien hecho debe contar una historia sin que el público necesite leer la tabla original.

1.1 Lo que aprenderemos esta semana

1. Entender la lógica de construcción de gráficos

  • Gráficos como “capas” que se suman (datos → mapeo → geometría → ajustes)
  • Por qué ggplot2 es diferente a Excel (control fino vs plantillas predefinidas)

2. Elegir el tipo de gráfico según la pregunta

  • Comparar categorías: barras
  • Ver distribuciones: histogramas
  • Mostrar relaciones: scatter plots
  • Seguir tendencias: líneas

3. Personalizar para comunicar mejor

  • Títulos, etiquetas y leyendas claras
  • Colores con propósito
  • Temas profesionales

Conexión con Semana 04

En la semana anterior usamos group_by() + summarise() para calcular KPIs por grupo. Esta semana convertiremos esas tablas en gráficos para comunicar hallazgos.

Semana 04 Semana 05
summarise() → tabla con ingreso por región geom_col() → barra comparativa que se lee en 3 segundos
filter() → filas del trimestre actual geom_line() → tendencia visual inmediata

El flujo siempre es el mismo: primero preparar los datos con dplyr, luego graficar con ggplot2.


1.2 Recursos de referencia

Antes de empezar, guarda estos dos recursos. Los usaremos durante toda la semana (y el resto del curso):

Recurso 1 — ¿Qué gráfico usar según mis datos?

from-data-to-viz.com

Árbol de decisión interactivo: seleccionas cuántas variables tienes y de qué tipo (numérica, categórica) → te dice qué geometría usar y te muestra el código en R. Úsalo cuando no estés seguro de qué tipo de gráfico hacer.

Recurso 2 — ¿Cómo se escribe en ggplot2?

ggplot2 cheat sheet

Resumen visual de todas las geometrías, mapeos y ajustes disponibles. Útil como referencia rápida durante la práctica.

2 Instalación y dataset

2.1 Instalación de ggplot2

2.2 Dataset de ejemplo: ventas de tecnología

Usaremos un dataset ampliado de ventas con 36 transacciones (el triple que en Semana 04). Esto nos permite hacer histogramas y scatter plots con suficientes datos.

En WebR, el dataset ya viene precargado. Si trabajas desde RStudio, descomenta la línea read.csv(...).

Qué contiene: 36 transacciones de venta de productos de tecnología, distribuidas en 3 trimestres y 3 regiones. Cada transacción tiene precio unitario, cantidad vendida e ingreso calculado.

3 La gramática de gráficos

En Excel seleccionamos datos y elegimos “gráfico de barras” del menú: rápido, pero limitado. ggplot2 usa una lógica diferente: construimos gráficos como capas que se acumulan, igual que construimos frases con sujeto + verbo + complemento.

Esto nos da ventajas clave para análisis de negocio:

  • Superponer capas (puntos + línea de tendencia en un mismo gráfico)
  • Controlar colores según variables del dataset (no manualmente)
  • Crear el mismo gráfico para distintos grupos automáticamente (facetas)
  • Reproducir el gráfico exacto la próxima semana con datos actualizados

3.1 Los tres componentes mínimos

Todo gráfico en ggplot2 necesita tres elementos:

La construcción de un gráfico en ggplot2 es acumulativa

Imagina que estás decorando un cuarto:

  1. Datosggplot(data = mis_datos) → entras al cuarto vacío (el lienzo en blanco). R reserva un espacio de trabajo para esa tabla, pero aún no pinta nada.

  2. Mapeos estéticosmapping = aes(x = ..., y = ..., color = ...) → decides qué va en qué pared (eje X, eje Y) y qué código de color usarás para cada tipo de mueble. Los ejes aparecen con sus etiquetas, pero el interior sigue vacío.

  3. Geometríageom_point(), geom_col(), geom_line(), etc. → por fin traes los muebles (los puntos, las barras, las líneas).

Estos tres elementos se conectan con el operador + (suma de capas).

Estos tres elementos se conectan con el operador + (suma de capas).


3.2 Construcción progresiva: paso a paso

Veremos cómo ggplot2 construye un gráfico en tres pasos. Primero preparamos la tabla con dplyr (lo que ya sabemos hacer):


Paso 1 — Solo los datos: el lienzo en blanco

R muestra un rectángulo gris vacío — es el lienzo. Todavía no sabe qué variables graficar ni cómo representarlas. Este es el punto de partida.


Paso 2 — Añadir el mapeo: definir ejes

Ahora el lienzo tiene ejes etiquetados con los rangos de las variables, pero sigue vacío en el interior. R ya sabe qué mostrar, pero aún no sabe cómo dibujarlo.

Nota: mapping = aes(...) es la forma completa. En la práctica se suele escribir abreviado aes(...) y R lo entiende igual.


Paso 3 — Añadir la geometría: elegir el tipo de gráfico

¿Qué hace cada parte?

Línea Pregunta que responde
ggplot(data = ing_region, ...) ¿Qué tabla voy a graficar?
mapping = aes(x = region, y = ingreso_total) ¿Qué variable va en cada eje?
geom_col() ¿Cómo represento visualmente los datos?

El operador + actúa como “y además agrega esta capa”. Podemos seguir sumando capas (títulos, colores, temas, facetas).


Ejercicio mental: leer código antes de ejecutarlo

Antes de correr este código, predice qué mostrará:

ggplot(data = ing_region, aes(x = region, y = ingreso_total)) +
  geom_point()

Piensa en los tres pasos:

  1. ¿Qué tabla usa? → ing_region (3 filas: Norte, Sur, Centro)
  2. ¿Qué va en los ejes? → X = región (categoría), Y = ingreso total (número)
  3. ¿Qué geometría? → geom_point() = puntos, no barras

Respuesta: Mismo gráfico que las barras, pero con puntos flotantes en lugar de columnas. Los ejes son idénticos.

Esto muestra que la lógica de construcción es siempre la misma — solo cambia la pieza de geometría.

4 Mapeos estéticos: dentro vs fuera de aes()

Una de las confusiones más comunes en ggplot2 es entender cuándo poner algo dentro de aes() y cuándo fuera.

4.1 Regla fundamental

Dentro de aes(): Cuando el valor depende de una variable del dataset.
→ “Quiero que el color cambie según la categoría de cada fila”

Fuera de aes(): Cuando el valor es fijo para todo el gráfico.
→ “Quiero que todas las barras sean azules”

4.2 Ejemplo con nuestros datos

Qué pasó: fill = "steelblue" está fuera de aes() porque no depende de ninguna variable. Todas las barras son azules.

Qué pasó: fill = region está dentro de aes() porque queremos que cada región tenga un color diferente. R asigna automáticamente un color distinto a cada región.


Advertencia

Error común

## Esto NO funciona como esperas
ggplot(ing_region, aes(x = region, y = ingreso_total, fill = "steelblue")) +
  geom_col()

Al poner fill = "steelblue" dentro de aes(), R interpreta que “steelblue” es el nombre de una variable (que no existe). No lo interpreta como “quiero color azul fijo”.

Regla práctica: Si escribes algo entre comillas o un número literal ("steelblue", 4), probablemente debe ir fuera de aes().

5 Geometrías según la pregunta

Cada tipo de pregunta de negocio tiene una geometría natural.

5.1 geom_col(): Comparar categorías con barras

Pregunta típica: “¿Qué región vendió más?”

Ya vimos el ejemplo básico. Ahora exploremos variantes útiles:

Qué cambió: intercambiamos x e y. Ahora las barras son horizontales.

Qué pasó: reorder(region, ingreso_total) reordena las regiones según su ingreso total. Esto hace el gráfico más fácil de leer: de un vistazo vemos cuál es la mejor región.


5.1.1 Mini-ejercicio

Usando la tabla ventas, calcula el ingreso total por categoría (Hardware vs Software) y grafícalo con barras. Ordena de mayor a menor.

Resultado esperado: Hardware debe tener una barra más alta que Software.


5.2 geom_histogram(): Ver distribuciones

Pregunta típica: “¿Cómo se distribuyen los precios de los productos que vendemos?”

Los histogramas agrupan valores continuos en “bins” (rangos) y cuentan cuántas observaciones caen en cada rango.

Qué pasó:

  • Solo necesitamos una variable (x = precio). R cuenta automáticamente cuántas transacciones tienen cada rango de precio.
  • bins = 10: divide el eje X en 10 rangos
  • fill y color: color de relleno y bordes de las barras

Cómo interpretar: vemos que la mayoría de transacciones tienen precios bajos (Mouse, accesorios), con algunos picos en precios altos (Laptops). Esto es esperado: vendemos más productos de bajo valor en cantidad que productos caros.


Qué pasó: ahora graficamos ingreso en lugar de precio. Vemos una distribución diferente: ingresos muy variados porque ingreso = precio * cantidad.


5.2.1 Mini-ejercicio

Crea un histograma de la variable cantidad. ¿Qué puedes concluir sobre las cantidades que vendemos por transacción?

Pregunta de análisis: ¿Vendemos más transacciones de pocas unidades o de muchas unidades?


5.3 geom_density(): Ver la forma de la distribución

Pregunta típica: “¿Cómo se distribuyen los precios que manejamos? ¿Hay un precio típico o son muy dispersos?”

La curva de densidad es similar al histograma pero continua: muestra la “forma” de la distribución sin depender del número de bins.

Cómo interpretar: los picos (modas) señalan los rangos de precio más comunes. Si hay dos picos separados (“distribución bimodal”), puede indicar dos segmentos de productos muy diferentes. En nuestros datos, vemos claramente la separación entre productos baratos (Mouse, Soporte) y caros (Laptop).

¿Histograma o densidad?

  • geom_histogram(): muestra conteos exactos (cuántas transacciones caen en cada rango)
  • geom_density(): muestra la forma general sin depender del tamaño del bin

Con pocos datos la curva puede verse irregular. Con cientos o miles de registros, la densidad suele ser más informativa que el histograma.


5.4 geom_point(): Mostrar relaciones entre variables

Pregunta típica: “¿Los productos más caros generan más ingreso por transacción?”

Los scatter plots (gráficos de dispersión) muestran la relación entre dos variables continuas.

Qué pasó: cada punto es una transacción. El eje X muestra el precio del producto, el eje Y la cantidad vendida.

Cómo interpretar: no vemos una relación clara (los puntos están dispersos). Esto sugiere que el precio del producto no determina directamente cuántas unidades vendemos por transacción.


Qué pasó: ahora vemos una relación más clara. Los productos más caros tienden a generar más ingreso (aunque no perfectamente lineal, porque ingreso = precio * cantidad).


Variante útil: agregar color según categoría para ver patrones por grupo:

Qué pasó: color = categoria dentro de aes() hace que Hardware y Software tengan colores diferentes. Ahora vemos que Hardware (puntos rojos) tiene precios más altos que Software (puntos azules).


5.4.1 Mini-ejercicio

Crea un scatter plot de cantidad (eje X) vs ingreso (eje Y). Colorea los puntos según region. ¿Qué región tiene transacciones de mayor ingreso?


5.5 geom_line(): Seguir tendencias temporales

Pregunta típica: “¿Cómo ha evolucionado nuestro ingreso trimestre a trimestre?”

Los gráficos de línea conectan puntos en orden, útiles para series de tiempo.

Primero preparamos la tabla:

Ahora graficamos:

Qué pasó:

  • geom_line(group = 1): dibuja la línea. group = 1 le dice a R que conecte todos los puntos (sin esto, no conectaría nada).
  • geom_point(): añade puntos sobre la línea para marcar cada trimestre.

Cómo interpretar: vemos una ligera tendencia al alza del Q1 al Q3 (crecimiento moderado).


Variante: ver evolución por región:

Qué pasó: color = region y group = region hacen que cada región tenga su propia línea con su propio color. Ahora podemos comparar la evolución de las tres regiones simultáneamente.


5.5.1 Mini-ejercicio

Calcula el número de transacciones por trimestre y grafícalo con línea. ¿En qué trimestre hubo más actividad comercial?


Decisión de geometría

Para cada pregunta, identifica qué geometría usarías:

  1. “¿Cuáles son los 3 productos más vendidos por cantidad?”
  2. “¿Existe relación entre el precio del producto y el ingreso generado?”
  3. “¿Cómo se distribuyen las cantidades vendidas por transacción?”
  4. “¿Cómo ha cambiado el ticket promedio trimestre a trimestre?”
  5. “¿Cómo se ‘forma’ la distribución de precios: simétrica, sesgada, bimodal?”

Respuestas: 1. geom_col() (barras, top 3 ordenados) 2. geom_point() (scatter plot) 3. geom_histogram() (distribución en conteos) 4. geom_line() (tendencia temporal) 5. geom_density() (forma de la distribución, sin depender de bins)

6 Personalización: comunicar mejor

Un gráfico sin títulos ni etiquetas claras es como un reporte sin conclusiones: técnicamente está “completo” pero no comunica nada.

6.1 Etiquetas con labs()

La función labs() controla todos los textos del gráfico:

Qué pasó: añadimos título, subtítulo, etiquetas de ejes y fuente de datos. Ahora el gráfico cuenta una historia completa.

Buenas prácticas:

  • Título: La idea principal (“Norte lidera”, no “Gráfico de ventas”)
  • Subtítulo: Contexto (período, filtros aplicados)
  • Ejes: Unidades claras (“USD”, “número de clientes”, etc.)
  • Caption: Fuente de datos

6.2 Temas: cambiar la apariencia general

Los temas controlan colores de fondo, grillas, fuentes, etc.

Cuándo usar cada tema

  • theme_minimal(): Presentaciones corporativas (limpio, moderno)
  • theme_bw(): Reportes académicos/técnicos (formal, tradicional)
  • theme_classic(): Publicaciones impresas (sin grillas ni distracciones)
  • theme_gray() (default): Generalmente evitar en entregas profesionales

6.3 Ajustes finos con theme()

Para control total, usamos theme():

Qué pasó:

  • legend.position = "none": oculta la leyenda (innecesaria porque el eje X ya dice las regiones)
  • plot.title: hace el título más grande y en negrita
  • axis.text.x: aumenta tamaño de etiquetas del eje X

6.4 Colores con propósito

Color fijo:

Color según variable:

Paleta personalizada:

Qué pasó: scale_fill_manual() nos permite asignar colores específicos a cada región.

Advertencia

Cuidado con los colores

  • Evita colores “gritones” (rojo/verde neón)
  • Considera daltonismo (evita rojo-verde como única distinción)
  • En duda, usa grises o azules (profesionales y neutrales)

6.4.1 Mini-ejercicio integrador

Crea un gráfico de barras del ingreso total por categoría (Hardware vs Software) con:

  • Título descriptivo
  • Etiquetas de ejes con unidades
  • Tema minimalista
  • Barras de color según categoría

7 Facetas: comparar múltiples grupos

A veces queremos ver el mismo gráfico para diferentes subgrupos.

7.1 facet_wrap(): dividir por una variable

Queremos ver la distribución de precios separada por región:

Qué pasó: facet_wrap(~ region) crea un panel separado para cada región, todos con la misma escala (facilita comparación).

Cómo interpretar: podemos ver si alguna región vende más productos de cierto rango de precio que otras.


Variante: permitir escalas diferentes en Y si los rangos son muy distintos:

Qué pasó: scales = "free_y" permite que cada panel tenga su propio rango en el eje Y. Útil cuando los grupos tienen tamaños muy diferentes.


7.2 facet_grid(): dividir por dos variables

Qué pasó: facet_grid(categoria ~ region) crea una matriz de gráficos. Filas = categoría, Columnas = región. Cada celda muestra la distribución de precios de esa combinación.


¿Cuándo usar facetas?

Facetas son útiles cuando:

  1. Quieres comparar la misma métrica para diferentes grupos
  2. Poner todo en un solo gráfico sería confuso (muchas barras/líneas superpuestas)
  3. Los grupos tienen patrones similares (facilita ver diferencias)

Ejemplo práctico: “Mostrar la evolución de ventas trimestre a trimestre para cada región” → 3 paneles con líneas temporales

8 Buenas prácticas de comunicación

8.1 Principios generales

1. Un gráfico = una idea

No intentes mostrar 5 cosas en un mismo gráfico. Si necesitas comunicar 5 insights, crea 5 gráficos.

2. Simplicidad > complejidad

Un gráfico de barras bien hecho comunica mejor que un gráfico 3D con efectos. Evita: - Gráficos de pie (especialmente con muchas categorías) - 3D sin propósito - Colores excesivos - Información redundante (números + barras + líneas del mismo dato)

3. Contexto siempre

  • Título descriptivo (no “Gráfico 1”)
  • Fuente de datos
  • Unidades de medida claras
  • Notas si hay filtros o supuestos importantes

8.2 Checklist antes de compartir un gráfico

Si la respuesta a alguna es “no”, mejora el gráfico antes de compartirlo.


8.3 Errores comunes en visualización de negocio

Advertencia

Error 1: Eje Y que no empieza en cero (en barras)

Para barras que representan cantidades (ventas, clientes, etc.), el eje Y debe empezar en cero. Si no, distorsionas la comparación visual.

Excepción: Gráficos de línea para tendencias (temperatura, precio de acciones) pueden no empezar en cero si tiene sentido para el negocio.

Advertencia

Error 2: Demasiadas categorías en barras

Si tienes 20 categorías, un gráfico de barras es ilegible. Opciones:

  1. Filtrar top 10
  2. Agrupar categorías menores en “Otros”
  3. Cambiar a tabla (si necesitas ver todos los valores)
Advertencia

Error 3: Colores sin significado

No uses colores diferentes solo “porque se ve bonito”. Los colores deben:

  • Representar una variable (categoría, rango de valores)
  • O ser todos iguales (si no hay distinción)

Mal: 5 barras de 5 colores diferentes sin razón
Bien: 5 barras del mismo color, o colores que representan regiones

9 Resumen ejecutivo

9.1 Flujo de trabajo para crear un gráfico

Paso 1: Preparar los datos (dplyr)

Usar group_by() + summarise() para obtener la tabla de KPIs que quiero graficar. Si el gráfico es sobre datos brutos (histograma, scatter), puedo saltar este paso.

Paso 2: Construir el gráfico en tres capas

ggplot(data = mi_tabla, mapping = aes(x = ..., y = ...))  # 1️⃣ lienzo + ejes
  + geom_...()                                             # 2️⃣ geometría
  + labs() + theme_...()                                   # 3️⃣ personalización

Paso 3: Elegir la geometría según la pregunta

Pregunta Geometría
¿Cuánto vendió cada región? geom_col()
¿Cómo evolucionó en el tiempo? geom_line()
¿Existe relación entre X e Y? geom_point()
¿Cuántas obs. caen en cada rango? geom_histogram()
¿Cómo es la forma de la distribución? geom_density()

Paso 4: Personalizar para comunicar

  • Títulos y etiquetas claras con labs()
  • Tema profesional (theme_minimal(), theme_bw())
  • Colores con propósito

Paso 5: Verificar

¿Alguien sin contexto entiende el mensaje? Si no, iterar.


9.2 Checklist de salida

Al final de esta semana, debes poder:


10 Preguntas de comprensión

1. Interpretación de código

Sin ejecutarlo, describe qué mostrará este gráfico: - ¿Qué hay en el eje X? - ¿Qué hay en el eje Y? - ¿Qué controla el color? - ¿Qué hace position = "dodge"?

Respuestas esperadas: - X: trimestres - Y: ingreso de cada transacción (no total) - Color: región - position = "dodge": barras lado a lado en lugar de apiladas

2. Decisión de diseño

Tienes una tabla con 50 productos y sus ventas. ¿Qué harías?

  1. Gráfico de barras con los 50 productos
  2. Gráfico de barras con top 10 + categoría “Otros”
  3. Tabla ordenada

Respuesta correcta: b) — 50 barras son ilegibles

3. Mapeo estético

¿Cuál de estos códigos mostrará puntos rojos?

Respuesta correcta: Opción B — color = "red" debe ir fuera de aes()


Conexión con el resto del curso

Semana 06 (siguiente): Importar datos reales (CSV, Excel) y hacer EDA (Exploratory Data Analysis) combinando dplyr + ggplot2.

Semanas 09-16: En machine learning, visualizaremos métricas de modelos, distribuciones de variables predictoras, y resultados de experimentos. Todo con la misma lógica de ggplot2.

Proyecto final: Los gráficos que crees serán parte fundamental de tu reporte/sustentación. Un análisis excelente con gráficos malos comunica poco.


10.1 Material adicional (opcional)

Si quieres profundizar:

Para esta semana, el material de preclase es suficiente. En clase practicaremos con datos reales paso a paso.