具有权重和类型相关节点和边的网络图
Network diagram with weight and type dependent nodes and edges
我有以下从 .xlsx 文件导入的简化数据库
df = pd.DataFrame({ 'from':['A','A','B','B','C','C'], 'to':['B', 'C','A','C,'A','B'],'weight':['10','5','25','2','4','8'],
'type':['typeA','typeA','typeB','typeB','typeC','typeC]})
与上述相同的数据库,为清楚起见,提供:
from: A A B B C C
to: B C A C A B
weight: 10 5 25 15 2 4
type: typeA typeA typeB typeB typeC typeC
我想创建一个具有以下特点的网络图表
- 节点
- 根据类型不同颜色不同
- 根据重量增加尺寸,例如节点A大小正比于(10 +5)
- 边
- 根据类型不同颜色不同
- 根据单个重量增加宽度,例如边AB宽度正比于10,边AC宽度正比于5
到目前为止,我只能生成未考虑此标准的网络图
G=nx.nx.from_pandas_edgelist(df, 'from', 'to', 'type', create_using=nx.Graph())
nx.draw(G, with_labels=True, node_size=1500, node_color="skyblue", pos=nx.fruchterman_reingold_layout(G))
如何使代码动态化并指定它以确保它满足标准,例如添加新数据或更改权重?
要从 pandas 边缘列表中动态获取图表,您可以使用 pandas itertuples
.
下面是它的基本工作原理:
for row in df.itertuples():
n = row[0] # 'from' is a reserved word so 'row.from' returns Syntax Error
u = row.to
w = row.weight
t = row.type
G.add_node(n, weight = w, type_ = t)
G.add_node(u, weight = w, type_ = t)
G.add_edge(n, u, weight = w, type_ = t) # weight of edge
现在让我们添加一些打印件,让您知道数据何时更改:
for row in df.itertuples():
u = row[1] # 'from' is a reserved word so 'row.from' returns Syntax Error
v = row.to
w = row.weight
t = row.type
if u in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[u] != new_data:
print("Node {} data update: {} {}".format(u, G.nodes(data=True)[u], new_data))
G.nodes()[u]["weight"] = w
G.nodes()[u]["type_"] = t
else:
G.add_node(u, weight = w, type_ = t)
if v in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[v] != new_data:
print("Node {} data update: {} {}".format(v, G.nodes(data=True)[v], new_data))
G.nodes()[v]["weight"] = w
G.nodes()[v]["type_"] = t
else:
G.add_node(v, weight = w, type_ = t)
G.add_edge(u, v, weight = w, type_ = t)
现在,像你假装的那样画网络:
每种类型都有一种颜色:
type_to_color = {
"typeA": "blue",
"typeB": "red",
"typeC": "green"
}
节点的颜色和权重可以这样获取:
n_colors = [type_to_color[u[1]] for u in g.nodes(data="type_")] # u[1] must be either typeA, typeB, typeC
n_sizes = [int(u[1]) for u in g.nodes(data="weight")] # you may want to scale these a little e.g n_sizes = [int(u[1])*10 for u in g.nodes(data="weight")]
边的颜色和权重可以这样得到:
edge_widths = [int(g[u][v]['weight']) for u,v in g.edges()]
edge_colors = [type_to_color[g[u][v]['type_']] for u,v in g.edges()]
接下来,像这样绘制网络:
nx.draw(g, with_labels = True, node_color = n_colors, edge_color=edge_colors ,node_size=n_sizes, width=edge_widths)
完整代码如下:
def get_graph_from_pandas(df, v = False):
G = nx.Graph()
for row in df.itertuples():
u = row[1] # 'from' is a reserved word so 'row.from' returns Syntax Error
v = row.to
w = row.weight
t = row.type
if u in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[u] != new_data:
print("Node {} data update: {} {}".format(u, G.nodes(data=True)[u], new_data))
G.nodes()[u]["weight"] = w
G.nodes()[u]["type_"] = t
else:
G.add_node(u, weight = w, type_ = t)
if v in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[v] != new_data:
print("Node {} data update: {} {}".format(v, G.nodes(data=True)[v], new_data))
G.nodes()[v]["weight"] = w
G.nodes()[v]["type_"] = t
else:
G.add_node(v, weight = w, type_ = t)
G.add_edge(u, v, weight = w, type_ = t)
return G
def draw_graph(g):
type_to_color = {
"typeA": "blue",
"typeB": "red",
"typeC": "green",
None:"black"
}
print([u[1] for u in g.nodes(data="type_")])
n_colors = [type_to_color[u[1]] for u in g.nodes(data="type_")] # u[1] must be either typeA, typeB, typeC
n_sizes = [int(u[1]) for u in g.nodes(data="weight")] # you may want to scale these a little e.g n_sizes = [int(u[1])*10 for u in g.nodes(data="weight")]
print(n_sizes)
edge_widths = [int(g[u][v]['weight']) for u,v in g.edges()] # you may want to scale these a little e.g edge_widths = [int(g[u][v]['weight'])*0.1 for u,v in g.edges()]
edge_colors = [type_to_color[g[u][v]['type_']] for u,v in g.edges()]
nx.draw(g, with_labels = True, node_color = n_colors, edge_color=edge_colors ,node_size=n_sizes, width=edge_widths)
return g
如有其他问题,请发表评论;)
这是 link 到 different example
这是你的例子:
import pandas as pd
import networkx as nx
df = pd.DataFrame({'from':['A','A','B','B','C','C'],
'to':['B', 'C','A','C','A','B'],
'weight':['10','5','25','2','4','8'],
'type':['typeA','typeA','typeB','typeB','typeC','typeC']})
df['weight'] = df['weight'].astype(int)
nodeweight = (df.groupby('from')['weight'].sum()*10).to_dict()
G=nx.nx.from_pandas_edgelist(df, 'from', 'to', ['type', 'weight'], create_using=nx.Graph())
edgeweights = [i[2]['weight'] for i in G.edges(data=True)]
nodelist = list(G.nodes)
edgelabels = {(i[0],i[1]):f'{i[0]}{i[1]}' for i in G.edges()}
nodesize = [nodeweight[i] for i in nodelist]
colorlist=[*'rbg']
pos = nx.fruchterman_reingold_layout(G)
nx.draw_networkx_nodes(G, pos, node_size=nodesize, node_color=colorlist, labels=True);
nx.draw_networkx_edges(G, pos, width=edgeweights);
nx.draw_networkx_labels(G, pos, font_size=10, font_family='sans-serif', font_color='white');
nx.draw_networkx_edge_labels(G,pos,edge_labels=edgelabels,font_color='red');
输出:
我有以下从 .xlsx 文件导入的简化数据库
df = pd.DataFrame({ 'from':['A','A','B','B','C','C'], 'to':['B', 'C','A','C,'A','B'],'weight':['10','5','25','2','4','8'],
'type':['typeA','typeA','typeB','typeB','typeC','typeC]})
与上述相同的数据库,为清楚起见,提供:
from: A A B B C C
to: B C A C A B
weight: 10 5 25 15 2 4
type: typeA typeA typeB typeB typeC typeC
我想创建一个具有以下特点的网络图表
- 节点
- 根据类型不同颜色不同
- 根据重量增加尺寸,例如节点A大小正比于(10 +5)
- 边
- 根据类型不同颜色不同
- 根据单个重量增加宽度,例如边AB宽度正比于10,边AC宽度正比于5
到目前为止,我只能生成未考虑此标准的网络图
G=nx.nx.from_pandas_edgelist(df, 'from', 'to', 'type', create_using=nx.Graph())
nx.draw(G, with_labels=True, node_size=1500, node_color="skyblue", pos=nx.fruchterman_reingold_layout(G))
如何使代码动态化并指定它以确保它满足标准,例如添加新数据或更改权重?
要从 pandas 边缘列表中动态获取图表,您可以使用 pandas itertuples
.
下面是它的基本工作原理:
for row in df.itertuples():
n = row[0] # 'from' is a reserved word so 'row.from' returns Syntax Error
u = row.to
w = row.weight
t = row.type
G.add_node(n, weight = w, type_ = t)
G.add_node(u, weight = w, type_ = t)
G.add_edge(n, u, weight = w, type_ = t) # weight of edge
现在让我们添加一些打印件,让您知道数据何时更改:
for row in df.itertuples():
u = row[1] # 'from' is a reserved word so 'row.from' returns Syntax Error
v = row.to
w = row.weight
t = row.type
if u in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[u] != new_data:
print("Node {} data update: {} {}".format(u, G.nodes(data=True)[u], new_data))
G.nodes()[u]["weight"] = w
G.nodes()[u]["type_"] = t
else:
G.add_node(u, weight = w, type_ = t)
if v in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[v] != new_data:
print("Node {} data update: {} {}".format(v, G.nodes(data=True)[v], new_data))
G.nodes()[v]["weight"] = w
G.nodes()[v]["type_"] = t
else:
G.add_node(v, weight = w, type_ = t)
G.add_edge(u, v, weight = w, type_ = t)
现在,像你假装的那样画网络:
每种类型都有一种颜色:
type_to_color = {
"typeA": "blue",
"typeB": "red",
"typeC": "green"
}
节点的颜色和权重可以这样获取:
n_colors = [type_to_color[u[1]] for u in g.nodes(data="type_")] # u[1] must be either typeA, typeB, typeC
n_sizes = [int(u[1]) for u in g.nodes(data="weight")] # you may want to scale these a little e.g n_sizes = [int(u[1])*10 for u in g.nodes(data="weight")]
边的颜色和权重可以这样得到:
edge_widths = [int(g[u][v]['weight']) for u,v in g.edges()]
edge_colors = [type_to_color[g[u][v]['type_']] for u,v in g.edges()]
接下来,像这样绘制网络:
nx.draw(g, with_labels = True, node_color = n_colors, edge_color=edge_colors ,node_size=n_sizes, width=edge_widths)
完整代码如下:
def get_graph_from_pandas(df, v = False):
G = nx.Graph()
for row in df.itertuples():
u = row[1] # 'from' is a reserved word so 'row.from' returns Syntax Error
v = row.to
w = row.weight
t = row.type
if u in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[u] != new_data:
print("Node {} data update: {} {}".format(u, G.nodes(data=True)[u], new_data))
G.nodes()[u]["weight"] = w
G.nodes()[u]["type_"] = t
else:
G.add_node(u, weight = w, type_ = t)
if v in G:
new_data = {'weight':w, 'type_':t}
if G.nodes(data=True)[v] != new_data:
print("Node {} data update: {} {}".format(v, G.nodes(data=True)[v], new_data))
G.nodes()[v]["weight"] = w
G.nodes()[v]["type_"] = t
else:
G.add_node(v, weight = w, type_ = t)
G.add_edge(u, v, weight = w, type_ = t)
return G
def draw_graph(g):
type_to_color = {
"typeA": "blue",
"typeB": "red",
"typeC": "green",
None:"black"
}
print([u[1] for u in g.nodes(data="type_")])
n_colors = [type_to_color[u[1]] for u in g.nodes(data="type_")] # u[1] must be either typeA, typeB, typeC
n_sizes = [int(u[1]) for u in g.nodes(data="weight")] # you may want to scale these a little e.g n_sizes = [int(u[1])*10 for u in g.nodes(data="weight")]
print(n_sizes)
edge_widths = [int(g[u][v]['weight']) for u,v in g.edges()] # you may want to scale these a little e.g edge_widths = [int(g[u][v]['weight'])*0.1 for u,v in g.edges()]
edge_colors = [type_to_color[g[u][v]['type_']] for u,v in g.edges()]
nx.draw(g, with_labels = True, node_color = n_colors, edge_color=edge_colors ,node_size=n_sizes, width=edge_widths)
return g
如有其他问题,请发表评论;)
这是 link 到 different example
这是你的例子:
import pandas as pd
import networkx as nx
df = pd.DataFrame({'from':['A','A','B','B','C','C'],
'to':['B', 'C','A','C','A','B'],
'weight':['10','5','25','2','4','8'],
'type':['typeA','typeA','typeB','typeB','typeC','typeC']})
df['weight'] = df['weight'].astype(int)
nodeweight = (df.groupby('from')['weight'].sum()*10).to_dict()
G=nx.nx.from_pandas_edgelist(df, 'from', 'to', ['type', 'weight'], create_using=nx.Graph())
edgeweights = [i[2]['weight'] for i in G.edges(data=True)]
nodelist = list(G.nodes)
edgelabels = {(i[0],i[1]):f'{i[0]}{i[1]}' for i in G.edges()}
nodesize = [nodeweight[i] for i in nodelist]
colorlist=[*'rbg']
pos = nx.fruchterman_reingold_layout(G)
nx.draw_networkx_nodes(G, pos, node_size=nodesize, node_color=colorlist, labels=True);
nx.draw_networkx_edges(G, pos, width=edgeweights);
nx.draw_networkx_labels(G, pos, font_size=10, font_family='sans-serif', font_color='white');
nx.draw_networkx_edge_labels(G,pos,edge_labels=edgelabels,font_color='red');
输出: