通过网络可视化集群中的节点及其连接

问题描述 投票:0回答:3

我有两个节点之间的连接列表,描述数据集中条目的相似性。

我正在考虑对条目及其连接进行可视化,以显示存在非常相似的条目的集群。

每个元组代表一对非常相似的节点。我为所有这些选择了权重为 1,因为这是必需的,但我希望所有边缘都一样厚。

我已经从

networkx
开始,问题是我现在不知道如何以有用的方式将相似的节点聚集在一起。

我有数据框中的连接列表:

smallSample = 
[[0, 1492, 1],
 [12, 937, 1],
 [16, 989, 1],
 [18, 371, 1],
 [18, 1140, 1],
 [26, 398, 1],
 [26, 1061, 1],
 [30, 1823, 1],
 [33, 1637, 1],
 [54, 1047, 1],
 [63, 565, 1]]

我通过以下方式创建图表:

import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
for index, row in CC.iterrows():
      G.add_edge(CC['source'].loc[index],CC['target'].loc[index], weight =1)
pos = nx.spring_layout(G, seed=7)
nx.draw_networkx_nodes(G, pos, node_size=5)
nx.draw_networkx_edges(G, pos, edgelist=G.edges(), width=0.5)
pos = nx.spring_layout(G, k=1, iterations=200)
plt.figure(3, figsize=(2000,2000), dpi =2) 

使用上面提供的小样本,结果如下所示:

我的真实 df 结果由数千个点组成:

Big Sample

如何将链接的节点分组在一起,以便更好地看到每个集群中有多少个节点?我不想让它们重叠得那么厉害,要掌握在大样本中到底有多少个真的不是那么容易。

python pandas matplotlib visualization networkx
3个回答
2
投票

如果您坚持使用networkx图来可视化您的数据,您可以定义相对于连接组件的[x,y]坐标,以更好地可视化图。一个例子可能是

Gcc=sorted(nx.connected_components(G), key=len, reverse=True)

cclens=[len(c) for c in Gcc]

pos_comp={ni:np.array([np.log(xi+1), yi]) 
          for yi in range(len(cclens)) 
          for (xi, ni) in enumerate(Gcc[yi]) }

nx.draw_networkx_nodes(G, pos_comp, node_size=10, alpha=0.45, linewidths=0.2)
nx.draw_networkx_edges(G, pos_comp, edgelist=G.edges(), width=0.5, alpha=0.1)
plt.title("Component length ordered")
plt.xlabel('Node ID')
plt.ylabel('Group ID')

输出结果如下所示:


1
投票

从 InfoVis 的角度来看,您可以做一些事情

  • 透明度和节点大小
    透明度可用于可视化重叠。您必须在这两个权衡之间进行选择:较低的透明度级别允许您可视化更多层,因为许多节点需要重叠,并且您应该增加节点大小。然而,较大的节点大小会使单个节点较少突出,并且节点边缘的可视化会增加混乱(禁用或使用较少的刻度边缘)。
    TL;DR:在较小的节点大小和较高的 alpha 值与较大的节点大小和较低的 alpha 值之间进行选择/播放。
  • 使用
    k
    参数来设置
    nx.spring_layout
    ,它越大,节点距离越远。默认为
    1/sqrt(len(G))
    稍微增加
    [1.2-1.7]/sqrt(len(G))
    可以让您更加清晰。

最后但并非最不重要的一点是,我建议您使用抖动,稍微打乱节点的位置并减少重叠(有很多关于抖动的论文和一些比我在这里选择的统一更好的版本,但它是最简单的实现。 )

数据集的一些重建

此代码创建了一个类似的数据集

import random
import numpy as np
import pandas as pd
from copy import deepcopy
import networkx as nx
import matplotlib.pyplot as plt
from math import sqrt

random.seed(7)
np.random.seed(7)

# Create a bigger dataset

smallSample = [
 [0, 1492, 1],
 [12, 937, 1],
 [16, 989, 1],
 [18, 371, 1],
 [18, 1140, 1],
 [26, 398, 1],
 [26, 1061, 1],
 [30, 1823, 1],
 [33, 1637, 1],
 [54, 1047, 1],
 [63, 565, 1]]

sample = deepcopy(smallSample)

AMOUT = 4000

present_nodes = list(set(x for edge in sample for x in edge))
i = 2
while i < AMOUT:
    source = target = None
    while source == target:
        if random.random() < 0.9:
            # Create at least one new node
            source = i
            if random.random() < 0.7: # High value for many small clusters
                # Create a second new node
                target = i = i+1
                present_nodes.append(target)
            else:
                target = random.choice(present_nodes)
            present_nodes.append(source)
        else: # Link existing ones
            source = random.choice(present_nodes)
            target = random.choice(present_nodes)
    i += 1
    sample.append([source, target, 1])

CC = pd.DataFrame(sample, columns=["source", "target", "weight"], dtype=int)

# Create the Graph
G = nx.Graph()
for index, row in CC.iterrows():
      G.add_edge(CC['source'].loc[index],CC['target'].loc[index], weight =1)

计算仓位

# Defaul k = 1/sqrt(len(G))
pos = nx.spring_layout(G, k=1/sqrt(len(G)), seed=7, iterations=100)
# cast the pos dict to an np.array
apos = np.fromiter(pos.values(), dtype=np.dtype((float, 2)))

默认外观

透明度

nx.draw_networkx_nodes(G, pos, node_size=10, alpha=0.45, linewidths=0.2)
nx.draw_networkx_edges(G, pos, edgelist=G.edges(), width=0.5, alpha=0.2)
plt.title("Transparency")
plt.figure(3, figsize=(2000,2000), dpi =2) 

使用较大的k值

这增加了节点之间的距离并减少了结块

pos15 = nx.spring_layout(G, k=1.5/sqrt(len(G)), seed=7, iterations=100) # Larger k to make it less clumpy

# cast the pos dict to an np.array
apos15 = np.fromiter(pos15.values(), dtype=np.dtype((float, 2)))

nx.draw_networkx_nodes(G, pos15, node_size=10, alpha=0.55, linewidths=0.2)
nx.draw_networkx_edges(G, pos15, edgelist=G.edges(), width=0.5, alpha=0.2)
plt.title("Larger k")
plt.figure(3, figsize=(2000,2000), dpi =2) 

添加抖动

JITTER = 0.025
jitter = np.random.uniform(low=-JITTER, high=JITTER, size=apos.shape)
jpos = {k:p for k,p in zip(pos.keys(), apos + jitter)}
jpos15 = {k:p for k,p in zip(pos15.keys(), apos15 + jitter)}

nx.draw_networkx_nodes(G, jpos, node_size=10, alpha=0.45, linewidths=0.2)
nx.draw_networkx_edges(G, jpos, edgelist=G.edges(), width=0.5, alpha=0.2)
plt.title("default + jitter")
plt.figure(3, figsize=(2000,2000), dpi =2) 
plt.show()

nx.draw_networkx_nodes(G, jpos15, node_size=10, alpha=0.55, linewidths=0.2)  # As nodes overlapp less I would increase the alpha level a bit
nx.draw_networkx_edges(G, jpos15, edgelist=G.edges(), width=0.5, alpha=0.2)
plt.title("larger k + jitter")
plt.figure(3, figsize=(2000,2000), dpi =2)


最后,需要调整一下参数来选择你喜欢的东西。


1
投票

我曾经使用 networkx + 导出

gml
文件来制作这些图表,以解决您使用名为 Cytoscape 的免费软件所询问的问题。它有一堆不同的可视化设置,可以很好地组织节点/边。

使用

nx.write_gml(G, "your_filename.gml")
输出到文件。然后,您可以将该文件导入 Cytoscape 并使用自动布局使节点很好地组织起来。我真的很喜欢
Prefuse Force Directed Layout
。然后将最终结果导出到图像以便在您需要的地方使用。

它有点笨重,不是一个编程解决方案,所以如果您需要重复创建这些图表,则无法工作,但我发现这样做可以产生最好看的最终结果。

© www.soinside.com 2019 - 2024. All rights reserved.