Dibujar una red de nodos en formación circular con enlaces entre nodos
-
24-10-2019 - |
Pregunta
Me gustaría dibujar un gráfico circular de nodos donde ciertos nodos tienen un enlace entre ellos. Aquí hay algunos ejemplos de gráficos de redes sociales:
(fuente: WRIGHTRESULT.COM)
(fuente: twit88.com)
¿Cómo se puede hacer esto con Matlab? ¿Es posible sin instalar un paquete separado?
Solución
Aquí hay una forma en que puedes hacer lo que quieras. Primero, genere puntos en el círculo que le interese
clear;
theta=linspace(0,2*pi,31);theta=theta(1:end-1);
[x,y]=pol2cart(theta,1);
A continuación, si conoce los pares de nodos que están conectados, puede omitir este paso. Pero en muchos casos, obtienes una matriz de conectividad de otros cálculos, y encuentra los índices de los nodos conectados de eso. Aquí, he creado una matriz booleana de conexiones. Entonces, si hay N
nodos, la matriz de conectividad es una NxN
matriz simétrica, donde si el i,j
El elemento es 1
, significa que tienes una conexión desde el nodo i
al nodo j
y 0
de lo contrario. Luego puede extraer los subíndices de los pares distintos de cero para obtener conexiones de nodo (solo se necesita el triángulo superior).
links=triu(round(rand(length(theta))));%# this is a random list of connections
[ind1,ind2]=ind2sub(size(links),find(links(:)));
Esta es la matriz de conectividad que generé con el código anterior.
Ahora solo necesitamos trazar las conexiones, una a la vez
h=figure(1);clf(h);
plot(x,y,'.k','markersize',20);hold on
arrayfun(@(p,q)line([x(p),x(q)],[y(p),y(q)]),ind1,ind2);
axis equal off
que le dará una figura similar a sus ejemplos
Otros consejos
Inspirado en lo último entrada en el blog por Cleve Moler, también podrías usar el gplot
función para dibujar un gráfico dado una matriz de adyacencia y coordenadas de nodo.
Aquí hay un ejemplo usando bucky
; Una parte de demostración de MATLAB que genera el gráfico de un icosaedro truncado (parece una pelota de fútbol). Solo usaremos su matriz de adyacencia para este ejemplo, ya que estamos diseñando los vértices en forma circular:
%# 60-by-60 sparse adjacency matrix
A = bucky();
N = length(A);
%# x/y coordinates of nodes in a circular layout
r = 1;
theta = linspace(0,2*pi,N+1)'; theta(end) = [];
xy = r .* [cos(theta) sin(theta)];
%# labels of nodes
txt = cellstr(num2str((1:N)','%02d'));
%# show nodes and edges
line(xy(:,1), xy(:,2), 'LineStyle','none', ...
'Marker','.', 'MarkerSize',15, 'Color','g')
hold on
gplot(A, xy, 'b-')
axis([-1 1 -1 1]); axis equal off
hold off
%# show node labels
h = text(xy(:,1).*1.05, xy(:,2).*1.05, txt, 'FontSize',8);
set(h, {'Rotation'},num2cell(theta*180/pi))
Podemos dar un paso más allá e intentar minimizar los cruces de borde. Es decir, queremos reorganizar los nodos para que los bordes estén lo más cerca posible de la circunferencia del círculo.
Esto se puede hacer al encontrar un simétrico permutación de la matriz que minimiza su ancho de banda (los no jeroes están más cerca de la diagonal)
p = symrcm(A);
A = A(p,p);
txt = txt(p);
El resultado en este caso:
Otras mejoras incluyen reemplazar líneas rectas con splines curvos para dibujar los bordes (de esa manera obtienes un gráfico más agradable similar al segundo que has mostrado), o usar diferentes colores para mostrar grupos de vértices y sus bordes (obviamente tú Necesita agrupar gráficos). Te dejaré esos pasos :)