Apunte 30 — Visualización de redes con ggraph y detección de comunidades

Analítica de Personas · Semestre otoño 2026 · Semana 12 · Prof. René Gempp

1. ¿Por qué visualizar redes?

Las métricas de centralidad que calculaste en el Apunte 29 son números. Un número te dice que la persona X tiene betweenness = 0.117. Pero no te dice dónde está X en la estructura, ni entre qué grupos funciona como puente, ni cuán aislado está un departamento del resto. Para eso necesitas un sociograma: la representación visual del grafo.

El paquete ggraph extiende ggplot2 para graficar redes. Su sintaxis es análoga: ggraph() reemplaza a ggplot(), geom_node_point() reemplaza a geom_point(), y geom_edge_link() es un geom nuevo para las aristas. Si sabes usar ggplot2, ya sabes la mitad de ggraph.

2. ggraph(): la gramática de los gráficos para redes

Un gráfico de red con ggraph tiene tres capas obligatorias:

  1. ggraph(grafo, layout = "...") — inicializa el gráfico y elige el layout.
  2. geom_edge_*() — dibuja las aristas.
  3. geom_node_*() — dibuja los nodos.
library(ggraph)

set.seed(42)  # reproducibilidad del layout

ggraph(red_tidy, layout = "fr") +
  geom_edge_link(alpha = 0.05, color = "grey60") +
  geom_node_point(aes(color = departamento), size = 2) +
  theme_graph()
set.seed() es obligatorio. Los layouts de fuerza (Fruchterman-Reingold, Kamada-Kawai) usan posiciones iniciales aleatorias. Si no fijas la semilla, cada vez que ejecutes el código obtendrás un gráfico distinto. Para que tu informe sea reproducible, siempre incluye set.seed() antes de ggraph().

3. Layouts: cómo posicionar los nodos

El layout determina la posición espacial de cada nodo. No hay un layout "correcto" — cada uno revela aspectos distintos de la estructura.

LayoutAlgoritmoCuándo usarlo
"fr"Fruchterman-ReingoldEl más popular. Nodos conectados se atraen, no conectados se repelen. Bueno para ver clusters.
"kk"Kamada-KawaiMinimiza la diferencia entre la distancia visual y la distancia en el grafo. Más estable que FR.
"stress"Stress majorizationSimilar a KK pero más robusto para redes grandes. Recomendado como alternativa a FR.
"circle"CircularNodos en un círculo. Útil para ver la densidad de aristas sin que los clusters dominen.
"linear"En líneaNodos en una línea horizontal. Útil para comparar dos mitades o para redes bipartitas.
# Comparar dos layouts
p1 <- ggraph(red_tidy, layout = "fr") +
  geom_edge_link(alpha = 0.03) +
  geom_node_point(size = 1) +
  labs(title = "Fruchterman-Reingold") +
  theme_graph()

p2 <- ggraph(red_tidy, layout = "kk") +
  geom_edge_link(alpha = 0.03) +
  geom_node_point(size = 1) +
  labs(title = "Kamada-Kawai") +
  theme_graph()

p1 + p2  # requiere library(patchwork)

4. Aristas: geom_edge_link()

Las aristas se dibujan con geom_edge_link() (líneas rectas) o geom_edge_arc() (arcos curvos). Los parámetros estéticos más útiles:

geom_edge_link(
  alpha = 0.06,              # transparencia (bajo = menos ruido visual)
  color = "grey60",           # color fijo
  aes(width = peso)          # grosor por peso (si la arista tiene peso)
)
Las aristas dominan el gráfico. Con 2.464 aristas, si no bajas la transparencia (alpha ≈ 0.03–0.08), el gráfico será una maraña ilegible. La transparencia es tu herramienta principal para controlar la legibilidad.

5. Nodos: geom_node_point() y etiquetas

geom_node_point(
  aes(
    color = departamento,        # color por atributo categórico
    size  = cent_betweenness     # tamaño por centralidad
  ),
  alpha = 0.7
)

# Etiquetas solo para los nodos más centrales
geom_node_text(
  aes(label = ifelse(
    cent_betweenness > quantile(cent_betweenness, 0.99),
    nombre, ""
  )),
  size = 2.5,
  repel = TRUE,           # evita superposición de etiquetas
  max.overlaps = 15
)
No etiquetes todos los nodos. Con 874 nodos, si pones etiquetas a todos, el gráfico será ilegible. Usa ifelse() para etiquetar solo los nodos con centralidad por encima de un umbral (e.g., percentil 99).

6. Facetas: facet_nodes()

Al igual que ggplot2 tiene facet_wrap(), ggraph tiene facet_nodes() para crear un panel por cada valor de un atributo de nodo:

ggraph(red_tidy, layout = "fr") +
  geom_edge_link(alpha = 0.05) +
  geom_node_point(aes(color = departamento), size = 1) +
  facet_nodes(~ departamento, scales = "free") +
  theme_graph()

Cada panel muestra la subred de un departamento. Las aristas que cruzan paneles se dibujan tenuemente. Esto permite comparar la estructura interna de cada departamento.

7. ¿Qué es una comunidad?

Una comunidad en una red es un subgrupo de nodos que están más densamente conectados entre sí que con el resto de la red. Es el equivalente reticular de un cluster.

La calidad de una partición en comunidades se mide con la modularidad (Q): compara la densidad de aristas dentro de cada comunidad con la que se esperaría al azar.

Q = Σc [ (aristas dentro de c / total aristas) − (aristas esperadas dentro de c / total aristas)² ]

Valores de Q por encima de 0.3–0.4 indican estructura comunitaria fuerte (Newman, 2006). Una Q ≈ 0.54 como la de InnovaCo indica comunidades muy marcadas.

8. Louvain: cluster_louvain()

El algoritmo de Louvain (Blondel, Guillaume, Lambiotte & Lefebvre, 2008) optimiza la modularidad de forma iterativa. Es rápido, escalable, y es el algoritmo más utilizado en la práctica.

set.seed(42)
comunidades <- cluster_louvain(red)

# ¿Cuántas comunidades?
length(unique(membership(comunidades)))

# ¿Qué tan buena es la partición?
modularity(comunidades)
# → Q ≈ 0.54 → estructura comunitaria fuerte

# Agregar al grafo
red_tidy <- red_tidy |>
  activate(nodes) |>
  mutate(comunidad = as.factor(membership(comunidades)))

# Visualizar
ggraph(red_tidy, layout = "fr") +
  geom_edge_link(alpha = 0.04) +
  geom_node_point(aes(color = comunidad), size = 1.5) +
  labs(title = "Comunidades detectadas por Louvain") +
  theme_graph()

9. Walktrap: cluster_walktrap()

El algoritmo walktrap (Pons & Latapy, 2006) detecta comunidades basándose en caminatas aleatorias: una caminata que empieza dentro de una comunidad tiende a quedarse ahí antes de salir.

com_walktrap <- cluster_walktrap(red)
modularity(com_walktrap)
Louvain vs. walktrap. Diferentes algoritmos pueden producir diferentes comunidades. No hay una partición "verdadera" — hay particiones más o menos útiles. En la práctica, se prueban ambos y se evalúa cuál produce comunidades más interpretables organizacionalmente.

10. Comparar comunidades con la estructura formal

La pregunta central del ONA es: ¿la estructura informal (comunidades detectadas) coincide con la estructura formal (departamentos del organigrama)?

# Tabla cruzada: comunidad × departamento
red_tidy |>
  activate(nodes) |>
  as_tibble() |>
  count(comunidad, departamento) |>
  pivot_wider(names_from = departamento, values_from = n, values_fill = 0)

Tres escenarios posibles:

Lo más valioso para el CEO es lo que NO coincide. Si las comunidades replican exactamente los departamentos, el ONA solo confirma lo que ya sabían. El hallazgo valioso es la discrepancia: el departamento que se fragmenta, el puente informal que cruza departamentos, o el silo que la reorganización no logró romper.

11. Marcos teóricos: Granovetter, Burt, Coleman

Granovetter (1973): la fuerza de los lazos débiles

La información novedosa no fluye por los lazos fuertes (amigos cercanos, colegas directos) sino por los lazos débiles (conocidos de otros departamentos). Los lazos fuertes conectan personas similares que comparten la misma información. Los lazos débiles cruzan círculos sociales y traen información nueva. Implicancia: las conexiones entre departamentos son potencialmente más valiosas para la innovación que las conexiones dentro del departamento.

Burt (1992): los huecos estructurales

Un hueco estructural (structural hole) es una brecha en la red entre dos grupos desconectados. Las personas que cierran estos huecos — los brokers — obtienen ventajas competitivas: acceso a información no redundante, control del flujo, y visibilidad ante múltiples audiencias. La betweenness centrality captura exactamente esta posición.

Coleman (1988): closure y capital social

James Coleman argumentó que las redes densas y cerradas (closure) facilitan la confianza, las normas compartidas y la cooperación. Burt argumentó que las redes abiertas con huecos (brokerage) facilitan la innovación. Ambos tienen razón: los equipos necesitan cohesión interna (closure) y conexiones externas (brokerage). Una red que solo tiene una u otra es disfuncional.

Para el memo ejecutivo. No necesitas citar a Granovetter o Burt por nombre. Pero sí necesitas el concepto: "los puentes interdepartamentales son más valiosos que las conexiones redundantes dentro del departamento" es Granovetter traducido a lenguaje de negocio.

12. Aplicaciones de ONA en people analytics

AplicaciónPreguntaMétrica clave
Diagnóstico de silos¿Qué departamentos no se hablan?Densidad interdepartamental, comunidades vs. organigrama
Key person risk¿Qué pasa si X se va?Betweenness, simulación de eliminación de nodo
Integración post-fusión¿Se integraron las dos empresas?Comunidades antes/después, aristas inter-empresa
Identificar influencers¿Quién mueve la opinión?Eigenvector centrality
Onboarding¿Los nuevos se están integrando?Degree y closeness de empleados nuevos a los 3, 6, 12 meses
DEI relacional¿Los grupos minoritarios están integrados en la red?Centralidad por grupo demográfico

13. Ética del ONA: privacidad, consentimiento y los límites del mapeo

Un mapa de red organizacional es una herramienta de poder. Saber quién conecta con quién, quién está aislado, quién es periférico — esa información puede usarse para apoyar o para controlar. La ética del ONA requiere tres condiciones:

  1. Consentimiento informado: los empleados deben saber que la encuesta de redes se va a analizar y para qué.
  2. Anonimización en los reportes: el mapa de red con nombres reales es una herramienta interna del equipo de analytics, no un entregable para el directorio. Los reportes ejecutivos deben referirse a roles, departamentos y patrones, no a personas identificables.
  3. Uso para mejorar, no para controlar: la finalidad del ONA es diagnosticar silos, planificar sucesiones y facilitar la colaboración — no identificar "resistentes al cambio" ni vigilar la comunicación informal.
La línea entre diagnóstico y vigilancia es delgada. Un CEO que pide "un mapa de quién habla con quién" puede estar buscando diagnóstico organizacional o puede estar buscando control social. El analista de people analytics tiene la responsabilidad de establecer los límites: qué preguntas se responden con datos de red y cuáles no se deben responder, aunque técnicamente se pueda.

14. Resumen del kit técnico y referencias

Función / paqueteUsoApunte
igraph::graph_from_data_frame()Crear grafo desde edgelist + nodos29 4
igraph::vcount(), ecount()Número de nodos y aristas29 5
igraph::graph.density(), diameter()Métricas globales de la red29 6
tidygraph::as_tbl_graph()Convertir igraph a formato tidy29 7
tidygraph::activate()Seleccionar tabla activa (nodos o aristas)29 7
centrality_degree()Centralidad de grado29 9
centrality_betweenness()Centralidad de intermediación29 10
centrality_closeness()Centralidad de cercanía29 11
centrality_eigen()Centralidad de vector propio29 12
igraph::delete_vertices()Simular eliminación de un nodo29 14
ggraph::ggraph()Inicializar gráfico de red30 2
ggraph::geom_edge_link()Dibujar aristas30 4
ggraph::geom_node_point()Dibujar nodos30 5
ggraph::facet_nodes()Paneles por atributo de nodo30 6
igraph::cluster_louvain()Detección de comunidades (Louvain)30 8
igraph::cluster_walktrap()Detección de comunidades (walktrap)30 9
igraph::membership()Asignación de comunidad por nodo30 8
igraph::modularity()Calidad de la partición30 7

Referencias