根据列名称为NetworkX节点分配颜色

时间:2019-03-25 16:40:46

标签: python bokeh networkx

我正在尝试使用NetworkX和Bokeh构建网络图。我正在使用NetworkX from_pandas_edgelist函数为图形添加数据。我想根据初始数据输入中的列为图的节点着色。

relation数据帧如下:

company   client

Google    AT&T
Google    Cisco       
Amazon    Facebook
Amazon    Snap
Amazon    Microsoft
Apple     Intel
Apple     IBM
Apple     Visa

上面的代码片段只是DataFrame的一部分。

我希望company中的所有节点以与client不同的颜色返回。

下面的代码生成一个网络图,其中所有节点都是相同的颜色。

G=nx.from_pandas_edgelist(relation, 'company', 'client')

# Show with Bokeh
plot = Plot(plot_width=1000, plot_height=800,
            x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))
plot.title.text = "Company - Client Network"

node_hover_tool = HoverTool(tooltips=[("Company Name", "@index")])
plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool())

graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))

graph_renderer.node_renderer.glyph = Circle(size=20)

graph_renderer.edge_renderer.glyph = MultiLine(line_color="red", line_alpha=0.8, line_width=1)
plot.renderers.append(graph_renderer)

output_file("interactive_graphs.html")
show(plot)

任何人都能提供的帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

在旧的Edit之后:

不能提供太多的上下文信息,因为我对bokeh并不十分熟悉,但是看起来您可以使用与我最初所做的类似的方法,而不必通过“ color_map”来完成绘制功能,因此必须粘贴graph_renderer.node_renderer.data_source.data['colors']中的数据 无论如何,好运,老兄。

relation = pd.DataFrame({
                "company":["Google", "Google", "Amazon", "Amazon", "Amazon",
                            "Apple", "Apple", "Apple"],
                "client":["AT&T", "Cisco", "Facebook", "Snap", "Microsoft",
                          "Intel", "IBM", "Visa"]})

G=nx.from_pandas_edgelist(relation, 'company', 'client')
colors = []

for node in G:
    if node in relation["client"].values:
        colors.append("blue")
    else: colors.append("green")

plot = Plot(plot_width=1000, plot_height=800,
            x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))
plot.title.text = "Company - Client Network"

node_hover_tool = HoverTool(tooltips=[("Company Name", "@index")])
plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool())

graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))

graph_renderer.node_renderer.data_source.data['colors'] = colors
graph_renderer.node_renderer.glyph = Circle(size=20, fill_color='colors')

graph_renderer.edge_renderer.glyph = MultiLine(line_color="red", line_alpha=0.8, line_width=1)
plot.renderers.append(graph_renderer)

output_file("boo.html")
show(plot)


答案 1 :(得分:0)

一个好问题,一个可以接受的答案(通过它我可以将代码扩展为基于Pandas数据框列的彩色节点)。

import warnings
warnings.filterwarnings("ignore", category=UserWarning)

import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd

df = pd.read_csv('pers_org.tsv', sep='\t')
# (TSV copied from a PostgreSQL database, hence the "id" column.)
df.sort_values(by=['id'])
'''
      id          person      organization
  0    1  Robert_Bigelow             BAASS
  1    2  Robert_Bigelow             AATIP
  2    3  Robert_Bigelow              NIDS
  3    4  Robert_Bigelow  Skinwalker_Ranch
  14   5   Luis_Elizondo             AATIP
  4    6   Colm_Kelleher             AATIP
  5    7   Colm_Kelleher              NIDS
  6    8   Colm_Kelleher  Skinwalker_Ranch
  7    9     Tom_DeLonge              TTSA
  8   10   Luis_Elizondo              TTSA
  9   11     Hal_Puthoff              TTSA
  10  12    Chris_Mellon              TTSA
  11  13   Douglas_Kurth           US_Navy
  12  14   Douglas_Kurth          Lockheed
  13  15   Douglas_Kurth             BAASS
'''

G = nx.from_pandas_edgelist(df, source='person', target='organization', \
    create_using=nx.DiGraph)
colors = []
for node in G:
    if node in df["person"].values:
        colors.append("lightblue")
    else: colors.append("lightgreen")

print(colors)
# ['lightblue', 'lightgreen', 'lightgreen', 'lightgreen', 'lightgreen',
#  'lightblue', 'lightblue', 'lightgreen', 'lightblue', 'lightblue',
#  'lightblue', 'lightblue', 'lightgreen', 'lightgreen']

plt.figure(figsize=(15,10))
# <Figure size 1500x1000 with 0 Axes>

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \
    node_size=1200, node_color=colors, linewidths=0.25, \
    font_size=10, font_weight='bold', with_labels=True)
plt.show()

另请参阅How to set colors for nodes in networkx python?

pers_org.tsv

id  person  organization
1   Robert_Bigelow  BAASS
2   Robert_Bigelow  AATIP
3   Robert_Bigelow  NIDS
4   Robert_Bigelow  Skinwalker_Ranch
5   Luis_Elizondo   AATIP
6   Colm_Kelleher   AATIP
7   Colm_Kelleher   NIDS
8   Colm_Kelleher   Skinwalker_Ranch
9   Tom_DeLonge TTSA
10  Luis_Elizondo   TTSA
11  Hal_Puthoff TTSA
12  Chris_Mellon    TTSA
13  Douglas_Kurth   US_Navy
14  Douglas_Kurth   Lockheed
15  Douglas_Kurth   BAASS

networkx_from_pandas_nodes_colored_by_df_column


尽管我在这里没有这样做,但是如果要添加节点边界并加粗节点边界线(节点边缘厚度:linewidths),请执行以下操作。

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \
    node_size=1200, node_color=colors, linewidths=2.0, \
    font_size=10, font_weight='bold', with_labels=True)

# Get current axis:
ax = plt.gca()
ax.collections[0].set_edgecolor('r')
# r : red (can also use #FF0000) | b : black (can also use #000000) | ...
plt.show()