# analisis-de-grafos-en-python-y-networkx
Análisis de Grafos en Python y NetworkX
Volver a la portada del cursoEjemplos de Visualización de Grafos
Sección 5 · Visualización de Grafos
Notebook: ejemplos de visualización de grafos
En el video anterior viste las piezas de un dibujo con NetworkX y Matplotlib: posiciones, colores, tamaños, grosores y etiquetas. En este notebook las aplicas a tres redes: el club de karate de Zachary, Los miserables y la red de productos de PyShop. Esta guía acompaña al notebook ejemplos-de-visualizacion y te dice qué buscar en cada figura y qué cifras la respaldan.
Objetivos
- Fijar posiciones reproducibles con
spring_layout(G, seed=42). - Colorear nodos por un atributo (club, categoría) o por comunidad.
- Escalar el tamaño de los nodos con una medida de centralidad y el grosor de las aristas con su peso.
- Etiquetar solo los nodos que importan.
- Leer la matriz de adyacencia como imagen y comparar layouts.
1. Karate: color por club
El grafo tiene 34 miembros y 78 amistades; el atributo club dice a qué bando se fue cada uno tras la división (17 con Mr. Hi y 17 con Officer).
K = nx.karate_club_graph()
pos = nx.spring_layout(K, seed=42)
colores = ["tab:blue" if K.nodes[n]["club"] == "Mr. Hi"
else "tab:orange" for n in K]
fig, ax = plt.subplots(figsize=(6, 5))
nx.draw_networkx(K, pos, node_color=colores, node_size=300,
font_size=8, ax=ax)
ax.axis("off")
Los nodos 0 (Mr. Hi, grado 16) y 33 (del bando de Officer, grado 17) quedan en lados opuestos, cada uno rodeado por su bando. Guarda pos: las siguientes figuras del karate usan las mismas posiciones para poder compararlas.
2. Karate: color por comunidad
Ahora el color sale de nx.community.louvain_communities(K, seed=42), que no conoce el atributo club. Encuentra 4 comunidades de 14, 10, 6 y 4 miembros, con modularidad 0.427. Pon las dos figuras lado a lado: cada comunidad cae casi entera dentro de un club. Las de 10 y 6 son solo de Mr. Hi, la de 4 solo de Officer y la de 14 tiene 13 de Officer y 1 de Mr. Hi. Louvain parte cada bando en subgrupos, pero casi no mezcla bandos.
Para colorear por comunidad conviene un diccionario nodo → índice de grupo:
grupos = nx.community.louvain_communities(K, seed=42)
grupo = {n: i for i, c in enumerate(grupos) for n in c}
nx.draw_networkx(K, pos, node_color=[grupo[n] for n in K],
cmap="tab10", node_size=300, font_size=8)
3. Los miserables: tamaño por intermediación
La red de personajes de la novela tiene 77 nodos y 254 aristas. Dibujada con todos los nombres es ilegible. La solución es que el tamaño cuente la historia y solo se etiqueten los personajes clave:
L = nx.les_miserables_graph()
bc_l = nx.betweenness_centrality(L)
top5 = sorted(bc_l, key=bc_l.get, reverse=True)[:5]
pos_l = nx.spring_layout(L, seed=42)
plt.figure(figsize=(11, 8))
nx.draw_networkx_edges(L, pos_l, alpha=0.2)
nx.draw_networkx_nodes(L, pos_l, node_size=[30 + 3000 * bc_l[n] for n in L])
nx.draw_networkx_labels(L, pos_l, labels={n: n for n in top5})
plt.axis("off")
Los tamaños van de 30 a 1740 puntos. Los cinco personajes etiquetados son Valjean (0.570), Myriel (0.177), Gavroche, Marius y Fantine. Valjean domina la figura: su intermediación es más del triple de la del segundo personaje. El 30 + evita que los nodos con intermediación 0 desaparezcan.
4. Red de PyShop por comunidad
La figura central del curso: los 41 productos coloreados por su comunidad de Louvain (con weight="weight" y seed=42) y las aristas con grosor proporcional al número de pedidos.
G = red_productos()
comunidades = sorted(nx.community.louvain_communities(G, weight="weight", seed=42),
key=len, reverse=True)
grupo = {n: i for i, c in enumerate(comunidades) for n in c}
pos = nx.spring_layout(G, seed=42, weight="weight")
pesos = np.array([w for _, _, w in G.edges(data="weight")])
grado = dict(G.degree())
etiquetas = {n: n for n in G if grado[n] >= 11 or n in PUENTES}
nx.draw_networkx_edges(G, pos, width=0.3 + 4 * pesos / pesos.max(), alpha=0.35)
nx.draw_networkx_nodes(G, pos, node_color=[grupo[n] for n in G], cmap="tab10",
node_size=[80 + 40 * grado[n] for n in G])
nx.draw_networkx_labels(G, pos, labels=etiquetas, font_size=9)
Aparecen 6 comunidades con modularidad 0.609: celulares y audio juntos (13 productos, con el cable usb-c), cómputo (7), cocina con el termo (7), deportes con la bocina bluetooth (7), hogar (6) y cuchillos, solo. Los grosores van de 0.84 a 4.3 puntos y los tamaños de 80 (cuchillos) a 680 (cable usb-c). Solo se etiquetan seis productos: los de grado 11 o más y los tres puentes. De las 136 aristas, 106 quedan dentro de una comunidad; las 30 restantes cruzan colores: 18 tocan uno de los tres productos puente y 11 de las 12 restantes unen hogar con cocina o con cómputo (foco inteligente, lámpara de escritorio, aspiradora robot).
5. La matriz de adyacencia como imagen
Otra forma de ver la misma red es su matriz de adyacencia: una fila y una columna por producto, con 1 donde hay arista.
orden = [n for c in comunidades for n in sorted(c)]
A = nx.to_numpy_array(G, nodelist=orden, weight="weight")
print(A.shape, int((A > 0).sum())) # (41, 41) 272
plt.imshow(A, cmap="Blues")
Hay 272 celdas con arista, el doble de las 136 aristas, porque en un grafo no dirigido la matriz es simétrica. Cada celda guarda el número de pedidos juntos (el máximo es 186). Al ordenar los productos por comunidad aparecen bloques oscuros sobre la diagonal: cada bloque es un grupo. El notebook marca los cortes entre comunidades con líneas; sin ese orden, la misma matriz parece ruido.
6. Layouts comparados
El notebook dibuja la red de PyShop en una cuadrícula de 2 × 2 con cuatro algoritmos de posición:
spring_layout: simula resortes; los productos muy conectados quedan cerca. Sinseed, cambia en cada ejecución.kamada_kawai_layout: intenta que la distancia en el dibujo refleje la distancia en pasos entre nodos; no usa semilla y da siempre el mismo dibujo.circular_layout: pone todos los nodos en un círculo; ignora la estructura, pero sirve para comparar aristas entre grupos si los nodos van ordenados.shell_layout(G, nlist=lv): un anillo por comunidad.
Ninguno es el correcto. Elige el que haga visible la pregunta que quieres responder.
Qué debes obtener
Seis figuras: karate por club y por comunidad (4 comunidades, modularidad 0.427), Los miserables con Valjean como el nodo más grande, PyShop con 6 colores, la matriz de 41 × 41 con bloques en la diagonal y la cuadrícula de layouts. Guarda cada figura con fig.savefig("red.png", dpi=150, bbox_inches="tight"). Si tus dibujos cambian entre ejecuciones, te faltó seed=42 en el layout o en Louvain. Como práctica, dibuja solo las aristas con peso de al menos 60 (48 aristas entre 30 productos) y compara la legibilidad con la red completa.