Analítica de Personas · Semestre otoño 2026 · Semana 12 · Prof. René Gempp
Durante 11 semanas has analizado datos donde cada fila era un empleado y cada columna un atributo: edad, departamento, satisfacción, salario. Esa perspectiva — llamada centrada en variables — es la columna vertebral de la estadística aplicada. Pero tiene un punto ciego: no ve las relaciones entre personas.
Un empleado puede tener alta satisfacción, buen desempeño y bajo riesgo de rotación según todos tus modelos — y ser, al mismo tiempo, el único canal de comunicación entre dos departamentos. Si se va, tu modelo de rotación no detecta el problema. Lo que necesitas es una herramienta que mire la estructura de las relaciones, no solo los atributos individuales.
Esa herramienta es el análisis de redes sociales (Social Network Analysis, SNA), y su aplicación en organizaciones se llama ONA (Organizational Network Analysis). En esta clase pasamos del paradigma centrado en variables al paradigma reticular — centrado en relaciones (Borgatti, Mehra, Brass & Labianca, 2009).
| Dimensión | Centrado en variables | Centrado en relaciones |
|---|---|---|
| Unidad de análisis | La persona | La relación (díada) |
| Estructura de datos | Tabla rectangular (CSV) | Grafo (nodos + aristas) |
| Pregunta típica | ¿Qué variables predicen Y? | ¿Qué posición en la red se asocia con Y? |
| Supuesto clave | Observaciones independientes | Las personas conectadas se influyen |
| Software | lm(), glm(), psych | igraph, tidygraph, ggraph |
igraph y ggraph. Esta semana construyes una red de personas. Las herramientas son las mismas; lo que cambia es lo que representan los nodos.
Un grafo es un objeto matemático compuesto por:
Cada arista puede tener propiedades adicionales:
En R, el paquete igraph representa grafos como objetos especiales que almacenan nodos, aristas y sus propiedades. No son data frames — son estructuras propias que requieren funciones específicas para manipular.
Cross y Parker (2004) identificaron cuatro redes que coexisten en toda organización:
| Tipo de red | Pregunta generadora | ¿Qué mide? |
|---|---|---|
| Comunicación | "¿Con quién hablas regularmente de trabajo?" | Flujo de información operativa |
| Consejo | "¿A quién acudes cuando necesitas consejo técnico?" | Flujo de conocimiento experto |
| Confianza | "¿En quién confías para compartir información delicada?" | Capital social relacional |
| Energía | "¿Después de interactuar con quién te sientes más motivado?" | Contagio emocional positivo |
graph_from_data_frame()El punto de entrada más común es un edgelist: una tabla con dos columnas (from, to) donde cada fila es una relación. Opcionalmente, una segunda tabla contiene los atributos de los nodos.
library(igraph)
# Edgelist: quién colabora con quién
aristas <- read_csv("innovaco_red_colaboracion.csv")
# Atributos de nodos: departamento, cargo, etc.
nodos <- empleados |>
filter(rotacion == "No") |>
select(id_empleado, nombre, departamento, cargo, antiguedad_anios)
# Crear el grafo
red <- graph_from_data_frame(
d = aristas, # edgelist
directed = FALSE, # colaboración = recíproca
vertices = nodos # atributos de nodos
)
red
# → IGRAPH UN-- 874 2464 --
# → U = undirected, N = named
directed = TRUE.
# ¿Cuántos nodos y aristas?
vcount(red) # → 874 nodos
ecount(red) # → 2464 aristas
# Acceder a nodos y aristas
V(red) # los vértices (nodos)
E(red) # las aristas (edges)
# Ver atributos de un nodo específico
V(red)["INN-0343"]$nombre
V(red)["INN-0343"]$departamento
# ¿Cuántos contactos tiene un nodo?
degree(red, v = "INN-0343")
Antes de analizar nodos individuales, necesitas entender la red completa.
# Densidad: aristas existentes / aristas posibles
graph.density(red)
# → ~0.006 → red muy dispersa
# Diámetro: camino más largo entre cualquier par
diameter(red)
# → 9 → máximo 9 saltos entre las personas más lejanas
# ¿La red tiene un solo componente?
is_connected(red)
components(red)$no
# Transitividad (clustering): ¿los amigos de mis amigos son mis amigos?
transitivity(red, type = "global")
# Distancia promedio entre todos los pares
mean_distance(red)
El paquete tidygraph envuelve un objeto igraph en una interfaz compatible con dplyr. El grafo tiene dos "tablas" internas — una de nodos y una de aristas — y puedes operar sobre cada una con los verbos que ya conoces: mutate(), filter(), arrange(), select().
library(tidygraph)
red_tidy <- as_tbl_graph(red)
red_tidy
# → # A tbl_graph: 874 nodes and 2464 edges
# Activar la tabla de nodos
red_tidy |>
activate(nodes) |>
as_tibble() |>
count(departamento, sort = TRUE)
# Activar la tabla de aristas
red_tidy |>
activate(edges) |>
as_tibble() |>
count(tipo, sort = TRUE)
# Agregar columnas a los nodos (como mutate en un df)
red_tidy <- red_tidy |>
activate(nodes) |>
mutate(n_contactos = centrality_degree())
activate(nodes) o activate(edges). Si no activas, opera sobre la última tabla activada (por defecto, nodos).
Una vez activada la tabla de nodos, puedes usar cualquier verbo de dplyr:
# Top 10 nodos por grado
red_tidy |>
activate(nodes) |>
as_tibble() |>
arrange(desc(n_contactos)) |>
select(nombre, departamento, cargo, n_contactos) |>
head(10)
# Filtrar: solo nodos de Desarrollo de Software
red_tidy |>
activate(nodes) |>
filter(departamento == "Desarrollo de Software")
# → Devuelve un subgrafo con solo esos nodos y sus aristas internas
La centralidad de grado (degree) es la métrica más simple: cuenta cuántas conexiones directas tiene un nodo. Normalizada, divide por el máximo posible (n − 1).
red_tidy <- red_tidy |>
activate(nodes) |>
mutate(cent_degree = centrality_degree(normalized = TRUE))
La centralidad de intermediación (betweenness) cuenta cuántos caminos más cortos entre otros pares de nodos pasan por un nodo dado. Es la métrica más importante para identificar brokers y evaluar key person risk.
red_tidy <- red_tidy |>
activate(nodes) |>
mutate(cent_betweenness = centrality_betweenness(normalized = TRUE))
La centralidad de cercanía (closeness) es el inverso de la suma de las distancias más cortas desde un nodo a todos los demás. Las personas con alta closeness están "geográficamente" en el centro de la red.
red_tidy <- red_tidy |>
activate(nodes) |>
mutate(cent_closeness = centrality_closeness(normalized = TRUE))
Cuándo importa: cuando necesitas que un mensaje llegue a todos con la menor distorsión posible (comunicación de crisis).
La centralidad de vector propio (eigenvector) no solo cuenta cuántas conexiones tienes, sino cuán conectados están tus contactos. Si tus pocos contactos son a su vez muy centrales, tu eigenvector centrality es alta. Es una medida de influencia por asociación.
red_tidy <- red_tidy |>
activate(nodes) |>
mutate(cent_eigenvector = centrality_eigen(scale = TRUE))
Cuándo importa: cuando buscas influencia indirecta. El PageRank de Google es una variante de eigenvector centrality: una página es "importante" si otras páginas "importantes" la enlazan.
| Métrica | Pregunta | Metáfora | Si sale de la empresa... |
|---|---|---|---|
| Degree | ¿Quién conoce a más gente? | El "gregario" | Se pierde un nodo activo, pero hay redundancia |
| Betweenness | ¿Quién conecta partes separadas? | El "puente" | Se fragmenta la red — riesgo máximo |
| Closeness | ¿Quién alcanza a todos más rápido? | El "centro geográfico" | Se alarga la distancia promedio |
| Eigenvector | ¿Quién conoce a los importantes? | El "bien conectado" | Se pierde acceso a la red de influencia |
# Correlación entre métricas
metricas |>
select(starts_with("cent_")) |>
cor() |>
round(3)
# → Si r es baja entre degree y betweenness,
# "popular" y "puente" son roles distintos
La forma más directa de evaluar el riesgo de persona clave es eliminar el nodo del grafo y comparar las métricas antes y después. Si el diámetro sube, la red se alarga. Si aparecen componentes nuevos, la red se fragmentó. Si la distancia promedio sube mucho más de lo esperado, la persona era un puente crítico.
# Identificar al broker principal
top_broker <- metricas |>
slice_max(cent_betweenness, n = 1)
# Métricas originales
mean_distance(red) # distancia promedio original
# Eliminar al broker
red_sin <- delete_vertices(red, top_broker$name)
# Métricas post-eliminación
mean_distance(red_sin) # ¿cuánto subió?
components(red_sin)$no # ¿se fragmentó?
diameter(red_sin) # ¿se alargó?
# Comparar con un nodo aleatorio
red_random <- delete_vertices(red, sample(V(red)$name, 1))
mean_distance(red_random)
# → Si la diferencia es grande, el broker era crítico
En este apunte aprendiste a construir grafos (graph_from_data_frame()), explorarlos (vcount(), ecount(), graph.density(), diameter()), operar sobre ellos con la interfaz tidy (tidygraph), calcular las cuatro métricas de centralidad (centrality_degree(), centrality_betweenness(), centrality_closeness(), centrality_eigen()), y simular la eliminación de nodos para evaluar el key person risk.
En el Apunte 30 aprenderás a visualizar estas redes con ggraph (layouts, colores, tamaños), a detectar comunidades (Louvain, walktrap) y a compararlas con la estructura formal (organigrama), y a conectar todo con los marcos teóricos de Granovetter, Burt y Coleman.