流行病模拟散点图显示异常,如何修复为常规散点图?
流行病传播模拟可视化异常问题排查与解决
问题描述
编写了branch()函数模拟流行病传播,尝试用散点图可视化传播情况:x轴为代际(generation),y轴为该代感染人数。但绘制出的散点图显示异常,甚至无法响应配色方案修改,且迭代次数越多问题越严重。
原绘图代码
import numpy as np import matplotlib.pyplot as plt import scipy.stats import networkx as nx N=np.zeros(1000) for x in range(99): infections = branch() list_length=len(infections) sumOfElements=0 for i in range(list_length): infectionsum=sumOfElements+infections[i] N[x] = infectionsum #print(infections) genhouse = [0,1,2,3,4,5,6,7,8,9] #s = [3*s**2 for s in infections] plt.scatter(genhouse, infections) #plt.scatter(x, y, s=area, c=colors, alpha=0.5) sum = np.sum(N) print("the average epidemic size is", sum) plt.title('Infections across Generations') plt.xlabel('Generation') plt.ylabel('Number of Infections') plt.show()
原流行病模拟函数
def branch(): r = .95 #reproduction number manygens = 10 #number of generations to simulate N=np.zeros(manygens+1) #how many children in each generation howmany = [2] G=nx.Graph() count = 0 G.add_node(1, gen = count) #gen 0 manynodes = 1 #how many nodes we currently have on the graph N[count] = 1 #one child in gen 0 for g in range(manygens): #run through generations thisgen = 0 #counter for infections this generation for node, gen in nx.get_node_attributes(G, "gen").items(): if gen == g: y = scipy.stats.poisson.rvs(mu=r, size=1) #see how many are infected if y < 1: #if less than 1 person is infected (no more reproduction from) break else: reset = 0 while y >= 1: G.add_node(manynodes + 1, gen = count + 1) #add the infected node G.add_edge(node, manynodes + 1) #connect to parent manynodes = manynodes + 1 #increase node counter y = y - 1 #each node we add take away 1 from y thisgen = thisgen + 1 count = count + 1 howmany.append(thisgen) #nx.draw_spring(G) turn this on to show the graph howmany.pop(-1) #print(howmany) return howmany
问题原因
- 绘图逻辑重复叠加:每次循环都调用
plt.scatter绘制一整组10个代际的散点,99次循环后同一张图上叠加了99组数据,点过度重叠导致视觉混乱,配色修改被大量重叠的点覆盖,无法显现效果。 - 模拟函数逻辑错误:
- 当某节点的感染数
y<1时使用break直接终止当前代的遍历,导致同代其他节点未被处理,统计的该代感染人数严重失真; count变量在单个节点处理完成后就递增,而非每代处理完后递增,导致代际标记混乱,返回的howmany数组数据异常;- 初始
howmany = [2]与gen0实际1个感染节点不符,初始数据错误。
- 当某节点的感染数
- 平均规模统计错误:
N[x] = infectionsum每次只赋值最后一次累加结果,未正确统计每次模拟的总感染人数,导致最终平均计算结果错误。
解决方案
1. 修正branch()模拟函数
def branch(): r = .95 # reproduction number manygens = 10 # number of generations to simulate G = nx.Graph() count = 0 G.add_node(1, gen=count) # gen 0 has 1 node manynodes = 1 howmany = [1] # gen0 initial infection count is 1 for g in range(manygens): # process each generation thisgen = 0 # Get all nodes in current generation current_gen_nodes = [node for node, attr in G.nodes(data=True) if attr['gen'] == g] for node in current_gen_nodes: y = scipy.stats.poisson.rvs(mu=r, size=1)[0] # get scalar value instead of array if y < 1: continue # skip this node, don't break the whole generation while y >= 1: manynodes += 1 G.add_node(manynodes, gen=count + 1) G.add_edge(node, manynodes) y -= 1 thisgen += 1 count += 1 # increment generation after processing all nodes in current gen howmany.append(thisgen) howmany.pop(-1) # remove the extra entry from manygens loop return howmany
2. 调整绘图逻辑(两种可选方式)
方式一:绘制所有模拟的散点(添加透明度区分)
import numpy as np import matplotlib.pyplot as plt import scipy.stats import networkx as nx num_simulations = 99 genhouse = np.arange(10) # 0-9 generations all_infections = [] total_cases = 0 for _ in range(num_simulations): infections = branch() all_infections.append(infections) total_cases += sum(infections) # 绘制单次模拟的散点,设置低透明度避免重叠遮挡 plt.scatter(genhouse, infections, alpha=0.2, color='blue') # 计算每代平均感染人数并绘制 avg_infections = np.mean(all_infections, axis=0) plt.scatter(genhouse, avg_infections, color='red', s=80, label='Average Infections') plt.title('Infections across Generations') plt.xlabel('Generation') plt.ylabel('Number of Infections') plt.legend() plt.show() print("The average epidemic size is", total_cases / num_simulations)
方式二:仅绘制每代平均感染人数的散点
import numpy as np import matplotlib.pyplot as plt import scipy.stats import networkx as nx num_simulations = 99 genhouse = np.arange(10) all_infections = [] total_cases = 0 for _ in range(num_simulations): infections = branch() all_infections.append(infections) total_cases += sum(infections) avg_infections = np.mean(all_infections, axis=0) plt.scatter(genhouse, avg_infections, color='darkorange', s=60) plt.title('Average Infections across Generations') plt.xlabel('Generation') plt.ylabel('Average Number of Infections') plt.show() print("The average epidemic size is", total_cases / num_simulations)
内容的提问来源于stack exchange,提问作者slacks37
相关产品推荐
相关产品推荐

