请问怎么使用python调整有向图的箭头方向?我的想法是增加一个节点的状态(感染性),如果他有感染性,就有向外的红色箭头,连线也为红色;没有感染性且身边节点都没有感染性,则箭头和连线均为默认方向且为黑色。
import networkx as nx
import matplotlib.pyplot as plt
import random
import numpy as np
#来生成一个有N个节点,连接概率为p,邻居为k的随机网络
N = 20
p = 0.25
k = 4
#er=nx.erdos_renyi_graph(N,p)
er = nx.random_graphs.watts_strogatz_graph(N,k,p)
for i in range(N):
er.nodes[i]['state'] = 'S'
edge_color = 'g'
gama = 0.5
beta = 0.1
ps= nx.spring_layout(er) #nx.spectral_layout(er)nx.circular_layout(er)nx.shell_layout(er)nx.spring_layout(er)#布置框架
colors = {"R": 'b', "I": 'r', "S": 'g'}
states= nx.get_node_attributes(er, 'state') # 获得节点的isCore属性
color=[colors[states[i]] for i in range(N)]
#nx.draw(er,ps,node_color =color ,with_labels=True,node_size=50)
nx.draw_networkx_nodes(er,ps,node_color =color ,node_size=50)
nx.draw_networkx_edges(er,ps ,width=1,arrows=True,arrowstyle='->')
plt.show()
def centrality(G):
#计算度中心性,降序
dc = nx.algorithms.centrality.degree_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def betweenness(G):
#计算介数中心性,降序
dc = nx.betweenness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def closeness(G):
#计算接近中心性,降序
dc = nx.closeness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def spread(G, beta, initial, func, gamma=0):
colors = {"R": 'b', "I": 'r', "S": 'g'}
y = []
n = len(G.nodes) # 总人数
for i in range(n): # 所有人默认为易感染
G.nodes[i]['state'] = 'S'
edge_color = 'g'
arrow_color = 'g'
s = n - initial # 易感染人数
desc_dc = func(G)
i_nodes = []
# 选择前inttial个度中心性最高的节点设为感染源
for i in range(initial):
G.nodes[desc_dc[0][0]]['state'] = 'I'
i_nodes.append(desc_dc[0][0])
desc_dc.remove(desc_dc[0])
y.append(((s, (len(i_nodes)), 0)))
# 开始传播,直到所有人被传染
r_nodes = nx.Graph()
while len(i_nodes) != 0:
print(s)
# 当前轮被传染的人数
i_temp = []
# 当前恢复人数 gamma 概率
for i in i_nodes:
if random.random() < gamma:
r_nodes.add_node(i)
i_nodes.remove(i)
G.nodes[i]['state'] = 'R'
i_nodes_temp = nx.Graph()
i_nodes_temp.add_nodes_from(i_nodes)
for i in i_nodes_temp.nodes:
# 按beta概率传染I节点的邻居节点
for node in G.neighbors(i):
r = random.random()
edge_color = 'r'
if r < beta and G.nodes[node]['state'] == 'S':
G.nodes[node]['state'] = 'I'
edge_color = 'r'
arrow_color = 'r'
i_temp.append(node)
for t in i_temp:
if t not in i_nodes:
i_nodes.append(t)
s = n - len(i_nodes) - len(r_nodes.nodes)
i = len(i_nodes)
r = len(r_nodes.nodes)
y.append((s, i, r))
states = nx.get_node_attributes(G, 'state') ############ 获得节点的属性
color = [colors[states[i]] for i in range(n)]
nx.draw(G, ps, node_color=color, with_labels=True, node_size=50)
nx.draw_networkx_edges(er, ps, width=1, arrows=True, arrowstyle='->')
plt.show()
return np.array(y)
#选择度中心性最高的5个点作为感染源
result = spread(er,0.3,5,centrality,0.1)
print(result)
plt.plot(result[:,0], 'g', label='Susceptibles')
plt.plot(result[:,1], 'r', label='Infectious')
plt.plot(result[:,2], 'b', label='Recovereds')
plt.legend(loc='right')
plt.xlabel('time')
plt.ylabel('number of people')
使用飞桨框架代码量少,难度低,预测效果更好,耗时较长
chatgpt:不喜勿喷
你可以使用 pydot 模块来调整有向图的箭头方向,该模块是 Graphviz 的 Python 接口,可以实现从 Python 代码生成图形。
以下是一些示例代码,将节点的状态作为图形的颜色属性,并根据该状态来调整边的颜色和箭头方向:
import networkx as nx
import pydot
import matplotlib.pyplot as plt
G = nx.DiGraph()
# 添加节点
G.add_nodes_from([1, 2, 3, 4])
# 添加有向边
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
# 添加节点的状态
for i in range(1, 5):
G.nodes[i]['state'] = 'S' # 默认为易感染状态
# 设置颜色映射
color_map = {'S': 'green', 'I': 'red', 'R': 'blue'}
# 遍历每个节点并设置颜色
node_color = [color_map[G.nodes[n]['state']] for n in G.nodes]
# 遍历每条边并设置颜色和箭头方向
edge_color = []
edge_style = []
for u, v in G.edges:
if G.nodes[u]['state'] == 'I':
edge_color.append('red')
edge_style.append('solid')
elif G.nodes[u]['state'] == 'S':
edge_color.append('black')
edge_style.append('dashed')
else:
edge_color.append('blue')
edge_style.append('dashed')
if G.nodes[u]['state'] == 'I':
edge_dir = 'forward'
else:
edge_dir = 'none'
G[u][v]['dir'] = edge_dir
# 将图形转换为 Pydot 图形对象
P = nx.drawing.nx_pydot.to_pydot(G)
# 遍历每个节点并设置颜色
for i, node in enumerate(P.get_nodes()):
node.set_style('filled')
node.set_fillcolor(node_color[i])
# 遍历每条边并设置颜色和箭头方向
for i, edge in enumerate(P.get_edges()):
edge.set_color(edge_color[i])
edge.set_style(edge_style[i])
edge.set_arrowtail('none')
edge.set_arrowhead(G[ edge.get_source() ][ edge.get_destination() ]['dir'])
# 绘制图形
graphviz_graph = pydot.graph_from_dot_data(P.to_string())[0]
graphviz_graph.write_png('example.png')
在上面的示例代码中,我们遍历了所有节点和边,根据节点的状态和边的情况设置了颜色和箭头方向。节点状态使用颜色映射设置节点的颜色,边的颜色和箭头方向根据节点的状态设置。如果一个节点被感染,则边的颜色为红色,箭头指向目标节点;否则边的颜色为黑色,没有箭头。最后,我们使用 pydot 将 NetworkX 图形转换为 Pydot 图形对象,并将图形保存为 PNG 文件
import networkx as nx
import matplotlib.pyplot as plt
import random
import numpy as np
# 生成一个有N个节点,连接概率为p,邻居为k的随机网络
N = 20
p = 0.25
k = 4
er = nx.random_graphs.watts_strogatz_graph(N, k, p)
# 为每个节点添加状态属性
for i in range(N):
er.nodes[i]['state'] = 'S'
# 定义传染病参数
gama = 0.5
beta = 0.1
# 设置节点颜色
colors = {"R": 'b', "I": 'r', "S": 'g'}
# 获取每个节点的状态并设置对应颜色
states = nx.get_node_attributes(er, 'state')
color = [colors[states[i]] for i in range(N)]
# 绘制初始网络图
ps = nx.spring_layout(er)
nx.draw_networkx_nodes(er, ps, node_color=color, node_size=50)
nx.draw_networkx_edges(er, ps, width=1, arrows=True, arrowstyle='->')
plt.show()
def centrality(G):
# 计算度中心性,降序排列
dc = nx.algorithms.centrality.degree_centrality(G)
return sorted(dc.items(), key=lambda x: x[1], reverse=True)
def betweenness(G):
# 计算介数中心性,降序排列
dc = nx.betweenness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1], reverse=True)
def closeness(G):
# 计算接近中心性,降序排列
dc = nx.closeness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1], reverse=True)
def spread(G, beta, initial, func, gamma=0):
# 初始化节点状态
for i in range(len(G.nodes)):
G.nodes[i]['state'] = 'S'
# 选择初始感染节点
desc_dc = func(G)
i_nodes = [desc_dc[i][0] for i in range(initial)]
# 记录每轮传播的状态
y = []
n = len(G.nodes)
s = n - initial
r_nodes = nx.Graph()
y.append((s, initial, 0))
# 开始传播
while len(i_nodes) != 0:
# 恢复节点
i_temp = []
for i in i_nodes:
if random.random() < gamma:
r_nodes.add_node(i)
i_nodes.remove(i)
G.nodes[i]['state'] = 'R'
# 传染节点
i_nodes_temp = nx.Graph()
i_nodes_temp.add_nodes_from(i_nodes)
for i in i_nodes_temp.nodes:
for node in G.neighbors(i):
if G.nodes[node]['state'] == 'S' and random.random() < beta:
G.nodes[node]['state'] = 'I'
# 设置连线颜色和箭头颜色
edge_color = 'r'
arrow_color = 'r'
if G.nodes[i]['state'] == 'R':
edge_color = 'b'
arrow_color = 'b
基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦💕(最新版更智能,功能更加强大)
要调整有向图的箭头方向,你可以在绘制网络时使用edge_color参数来指定边的颜色。在spread函数中,当传染发生时,你可以将连线和箭头的颜色都设置为红色,表示传染发生了。如果节点没有感染性或周围所有节点也没有感染性,则连线和箭头会保持默认状态(黑色)。下面是一个修改过的代码示例:
python
import networkx as nx
import matplotlib.pyplot as plt
import random
import numpy as np
#来生成一个有N个节点,连接概率为p,邻居为k的随机网络
N = 20
p = 0.25
k = 4
#er=nx.erdos_renyi_graph(N,p)
er = nx.random_graphs.watts_strogatz_graph(N,k,p)
for i in range(N):
er.nodes[i]['state'] = 'S'
gama = 0.5
beta = 0.1
ps= nx.spring_layout(er) #nx.spectral_layout(er)nx.circular_layout(er)nx.shell_layout(er)nx.spring_layout(er)#布置框架
colors = {"R": 'b', "I": 'r', "S": 'g'}
states= nx.get_node_attributes(er, 'state') # 获得节点的isCore属性
color=[colors[states[i]] for i in range(N)]
#nx.draw(er,ps,node_color =color ,with_labels=True,node_size=50)
nx.draw_networkx_nodes(er,ps,node_color =color ,node_size=50)
nx.draw_networkx_edges(er,ps ,width=1,arrows=True,arrowstyle='->', edge_color='k')
plt.show()
def centrality(G):
#计算度中心性,降序
dc = nx.algorithms.centrality.degree_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def betweenness(G):
#计算介数中心性,降序
dc = nx.betweenness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def closeness(G):
#计算接近中心性,降序
dc = nx.closeness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def spread(G, beta, initial, func, gamma=0):
colors = {"R": 'b', "I": 'r', "S": 'g'}
y = []
n = len(G.nodes) # 总人数
for i in range(n): # 所有人默认为易感染
G.nodes[i]['state'] = 'S'
s = n - initial # 易感染人数
desc_dc = func(G)
i_nodes = []
# 选择前inttial个度中心性最高的节点设为感染源
for i in range(initial):
G.nodes[desc_dc[0][0]]['state'] = 'I'
i_nodes.append(desc_dc[0][0])
desc_dc.remove(desc_dc[0])
y.append(((s, (len(i_nodes)), 0)))
# 开始传播,直到所有人被传染
r_nodes = nx.Graph()
while len(i_nodes) != 0:
print(s)
# 当前轮被传染的人数
i_temp = []
# 当前恢复人数 gamma 概率
for i in i_nodes:
if random.random() < gamma:
r_nodes.add_node(i)
i_nodes.remove(i)
G.nodes[i]['state'] = 'R'
i_nodes_temp = nx.Graph()
i_nodes_temp.add_nodes_from(i_nodes)
for i in i_nodes_temp.nodes:
# 按beta概率传染I节点的邻居节点
for node in G.neighbors(i):
r = random.random()
edge_color = 'k'
arrow_color = 'k'
if r < beta and G.nodes[node]['state'] == 'S':
G.nodes[node]['state'] = 'I'
edge_color = 'r'
arrow_color = 'r'
i_temp.append(node)
for t in i_temp:
if t not in i_nodes:
i_nodes.append(t)
s = n - len(i_nodes) - len(r_nodes.nodes)
# 更新网络中每个节点的颜色和连线箭头颜色
states = nx.get_node_attributes(G, 'state')
color = [colors[states[i]] for i in range(n)]
arrows = [('k' if states[node] == 'S' else 'r') for node in G.nodes]
# 绘制更新后的网络
nx.draw_networkx_nodes(G, ps, node_color=color, node_size=50)
nx.draw_networkx_edges(G, ps ,width=1, arrows=True, arrowstyle='->', edge_color=arrows)
plt.show()
return np.array(y)
选择度中心性最高的5个点作为感染源,并调用spread函数进行传播模拟
result = spread(er,0.3,5,centrality,0.1)
print(result)
绘制传染病模型图表
plt.plot(result[:,0], 'g', label='Susceptibles')
plt.plot(result[:,1], 'r', label='Infectious')
plt.plot(result[:,2], 'b', label='Recovereds')
plt.legend(loc='right')
plt.xlabel('time')
plt.ylabel('number of people')
在上面的代码中,我修改了spread函数,添加了一些代码来更新每个节点的颜色并及时绘制网络。得到的结果是一个具有红色箭头方向的有向图,表示传染过程中的传播方向。
要实现有向图的箭头方向调整,可以使用NetworkX中的DiGraph类来构建有向图。在节点属性中增加一个感染性状态,根据节点的感染性状态来确定连线和箭头的颜色和方向。具体实现方法如下:
使用DiGraph类来创建有向图,可以使用add_edge()方法来添加有向边。
在节点属性中增加一个状态属性,可以使用set_node_attributes()方法来设置节点属性。
根据节点的状态属性来确定连线和箭头的颜色和方向,可以使用draw_networkx_edges()方法来绘制连线和箭头。其中,使用edge_color参数来设置连线颜色,使用arrowstyle参数来设置箭头样式,使用arrowsize参数来设置箭头大小。
下面是修改后的代码示例:
import networkx as nx
import matplotlib.pyplot as plt
import random
import numpy as np
#来生成一个有N个节点,连接概率为p,邻居为k的随机网络
N = 20
p = 0.25
k = 4
#er=nx.erdos_renyi_graph(N,p)
er = nx.random_graphs.watts_strogatz_graph(N,k,p)
# 使用DiGraph类来创建有向图
G = er.to_directed()
# 在节点属性中增加一个状态属性
for i in range(N):
G.nodes[i]['state'] = 'S'
# 设置节点属性
nx.set_node_attributes(G, 'S', 'state')
ps= nx.spring_layout(er) #nx.spectral_layout(er)nx.circular_layout(er)nx.shell_layout(er)nx.spring_layout(er)#布置框架
colors = {"R": 'b', "I": 'r', "S": 'g'}
states= nx.get_node_attributes(G, 'state') # 获得节点的状态属性
color=[colors[states[i]] for i in range(N)]
# 绘制节点和连线
nx.draw_networkx_nodes(er,ps,node_color =color ,node_size=50)
for edge in G.edges():
# 根据节点状态属性来确定连线颜色和箭头方向
if G.nodes[edge[0]]['state'] == 'I':
edge_color = 'r'
arrow_color = 'r'
arrowstyle = '-|>'
else:
edge_color = 'k'
arrow_color = 'k'
arrowstyle = '-'
nx.draw_networkx_edges(G, ps, edgelist=[edge], edge_color=edge_color, width=1, arrows=True, arrowstyle=arrowstyle, arrowsize=10, arrow_color=arrow_color)
plt.show()
需要注意的是,使用DiGraph类创建有向图后,原本的布局可能不再适用,需要重新进行布局。此外,在绘制连线时,需要根据节点状态属性来确定连线颜色和箭头方向,需要对每条边进行判断并绘制。
你把数据和代码发过来
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在SIR传染病模型中显示传染方向可以通过改变边的颜色和箭头方向来实现。可以设置节点的感染状态,对于有向边的可视化,可以使用networkx的带有箭头的图形来表示。
下面是一个示例代码,用于实现带有箭头的边的可视化:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edge('A', 'B')# 实现从'A'到'B'的单向链接,即A节点指向B节点。
G.add_edge('B','C')
pos = nx.spring_layout(G) #以Spring layout布局方式排序
#绘制图形
nx.draw_networkx_nodes(G, pos, node_size=1000, node_color='lightblue')
nx.draw_networkx_edges(G, pos, edge_color='blue', arrows=True)
nx.draw_networkx_labels(G, pos, font_size=20, font_family='serif', font_color='black')
plt.title('Directed Graph')
plt.axis('off')
plt.show()
接下来可以将以上代码中的每个节点的状态进行分类,最终确定每个节点的状态(感染/未感染),然后将边缘颜色设置为红色或绿色来显示方向(感染/未感染)。
下面是一个使用python实现SIR传染病模型,可以显示传染方向的代码:
import networkx as nx
import matplotlib.pyplot as plt
import random
import numpy as np
#来生成一个有N个节点,连接概率为p,邻居为k的随机网络
N = 20
p = 0.25
k = 4
#er=nx.erdos_renyi_graph(N,p)
er = nx.random_graphs.watts_strogatz_graph(N,k,p)
for i in range(N):
er.nodes[i]['state'] = 'S'
edge_color = 'g'
gama = 0.5
beta = 0.1
ps= nx.spring_layout(er) #nx.spectral_layout(er)nx.circular_layout(er)nx.shell_layout(er)nx.spring_layout(er)#布置框架
colors = {"R": 'b', "I": 'r', "S": 'g'}
states= nx.get_node_attributes(er, 'state') # 获得节点的state属性
color=[colors[states[i]] for i in range(N)]
#nx.draw(er,ps,node_color =color ,with_labels=True,node_size=50)
nx.draw_networkx_nodes(er,ps,node_color =color ,node_size=50)
nx.draw_networkx_edges(er,ps ,width=1,arrows=True,arrowstyle='->')
plt.show()
def centrality(G):
#计算度中心性,降序
dc = nx.algorithms.centrality.degree_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def betweenness(G):
#计算介数中心性,降序
dc = nx.betweenness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def closeness(G):
#计算接近中心性,降序
dc = nx.closeness_centrality(G)
return sorted(dc.items(), key=lambda x: x[1],reverse = True)
def spread(G, beta, initial, func, gamma=0):
colors = {"R": 'b', "I": 'r', "S": 'g'}
y = []
n = len(G.nodes) # 总人数
for i in range(n): # 所有人默认为易感染
G.nodes[i]['state'] = 'S' # 设置所有节点状态为S
s = n - initial # 易感染人数
desc_dc = func(G)
i_nodes = []
# 选择前inttial个度中心性最高的节点设为感染源
for i in range(initial):
G.nodes[desc_dc[0][0]]['state'] = 'I'
i_nodes.append(desc_dc[0][0])
desc_dc.remove(desc_dc[0])
y.append(((s, (len(i_nodes)), 0)))
# 开始传播,直到所有人被传染
r_nodes = nx.Graph()
while len(i_nodes) != 0:
# 当前轮被传染的人数
i_temp = []
# 当前恢复人数 gamma 概率
for i in i_nodes:
if random.random() < gamma:
r_nodes.add_node(i)
i_nodes.remove(i)
G.nodes[i]['state'] = 'R'
i_nodes_temp = nx.Graph()
i_nodes_temp.add_nodes_from(i_nodes)
for i in i_nodes_temp.nodes:
# 按beta概率传染I节点的邻居节点
for node in G.neighbors(i):
r = random.random()
if G.nodes[node]['state'] == 'S':
if G.nodes[i]['state'] == 'I':
if r < beta:
G.nodes[node]['state'] = 'I'
i_temp.append(node)
edge_color = 'r'
arrow_color = 'r'
else:
edge_color = 'g'
arrow_color = 'g'
else:
edge_color = 'b'
arrow_color = 'b'
G[node][i]['edge_color'] = edge_color
G[node][i]['arrow_color'] = arrow_color
for t in i_temp:
if t not in i_nodes:
i_nodes.append(t)
s = n - len(i_nodes) - len(r_nodes.nodes)
i = len(i_nodes)
r = len(r_nodes.nodes)
y.append((s, i, r))
edge_color = [G[u][v]['edge_color'] for u, v in G.edges()]
arrow_color = [G[u][v]['arrow_color'] for u, v in G.edges()]
states = nx.get_node_attributes(G, 'state') ############ 获得节点的state属性
color = [colors[states[i]] for i in range(n)]
nx.draw_networkx_nodes(G, ps, node_color=color, with_labels=True, node_size=50)
nx.draw_networkx_edges(G, ps, width=1, arrows=True, arrowstyle='->', edge_color=edge_color)
plt.show()
return np.array(y)
#选择度中心性最高的5个点作为感染源
result = spread(er,0.3,5,centrality,0.1)
print(result)
plt.plot(result[:,0], 'g', label='Susceptibles')
plt.plot(result[:,1], 'r', label='Infectious')
plt.plot(result[:,2], 'b', label='Recovereds')
plt.legend(loc='right')
plt.xlabel('time')
plt.ylabel('number of people')
在这段代码中,每个被源感染的节点都会将自己的“state”属性设置为“I”,然后从这个节点发送颜色为红色的有向连线。对于未感染节点之间的连线,沿着它们默认的方向显示黑色有向连线,当目标节点的状态为“I”时显示向红色的箭头。
如果我的回答解决了您的问题,请采纳!
引用chatGPT作答,要调整有向图的箭头方向,需要修改边的起点和终点。在 NetworkX 中,边是从源节点指向目标节点的,所以我们只需要交换源节点和目标节点的标识符,就可以改变箭头方向。例如,如果要将节点1指向节点2的有向边变为节点2指向节点1的有向边,可以使用以下代码:
G = nx.DiGraph() # 创建一个有向图
G.add_edge(1, 2) # 添加有向边
# 将有向边的方向反转
G.add_edge(2, 1)
G.remove_edge(1, 2)
根据您的需求,可以使用类似的方法改变边的方向。具体来说,您可以在每次迭代中,检查每个节点的状态,如果该节点具有感染性,就将其邻居节点连接到该节点,否则就将该节点连接到邻居节点。如果该节点的所有邻居节点都没有感染性,则不需要改变边的方向。代码示例如下:
for node in G.nodes:
# 检查节点的状态
if G.nodes[node]['state'] == 'I':
# 将邻居节点连接到该节点
for neighbor in G.neighbors(node):
G.add_edge(neighbor, node, color='r', arrowsize=20, arrowstyle='->')
else:
has_infected_neighbor = False
# 检查邻居节点的状态
for neighbor in G.neighbors(node):
if G.nodes[neighbor]['state'] == 'I':
has_infected_neighbor = True
break
# 如果没有感染性邻居,则不需要改变边的方向
if not has_infected_neighbor:
continue
# 将该节点连接到所有感染性邻居节点
for neighbor in G.neighbors(node):
if G.nodes[neighbor]['state'] == 'I':
G.add_edge(node, neighbor, color='r', arrowsize=20, arrowstyle='->')
在这个示例代码中,我们遍历所有节点,并检查它们的状态。如果节点具有感染性,我们将该节点的邻居节点连接到该节点,从而实现红色箭头的方向。如果节点没有感染性,我们检查它是否有感染性邻居节点。如果没有,则不需要改变边的方向。否则,我们将该节点连接到所有感染性邻居节点,从而实现红色箭头的方向。
人群接触网络中的SIR疫情模拟——Python实现
可以借鉴下
https://blog.csdn.net/m0_72662900/article/details/126571764