无需Pandas,在同一张图中绘制CSV文件的SIR疫情模拟曲线
修正后的疫情SIR曲线绘图代码
你的代码主要存在几个核心问题:没有生成正确的X轴天数序列、未将数据归一化到0-1的比例范围、绘图逻辑未正确关联X/Y轴数据。以下是修正后的完整代码及说明:
import numpy as np import matplotlib.pyplot as plt s = [] i = [] r = [] with open("pan.csv","r") as f: # 读取行并去除换行符,避免分割后出现空元素 lis = [line.strip().split(",") for line in f] # 读取120天的数据(对应原代码的range(1,121)) for n in range(1, 121): s.append(int(lis[n][0])) i.append(float(lis[n][1])) r.append(float(lis[n][2])) # 生成X轴:1到120天的序列 days = np.arange(1, 121) # 数据归一化到0-1范围(假设S是人数,I/R已为比例;若都是人数,看下方补充) total_pop = s[0] / (1 - i[0] - r[0]) # 用第一天数据反推总人数 s_normalized = [num / total_pop for num in s] # 创建绘图对象并绘制三条曲线 fig, ax = plt.subplots() ax.plot(days, s_normalized, label='易感者(S)') ax.plot(days, i, label='感染者(I)') ax.plot(days, r, label='康复者(R)') # 设置图表属性 ax.set_xlabel('天数') ax.set_ylabel('比例(0-1)') ax.set_title('疫情SIR模型模拟曲线') ax.set_ylim(0, 1) # 强制Y轴固定在0-1区间 ax.legend() # 显示曲线图例 plt.show()
补充:若CSV中S/I/R都是绝对人数
只需要修改归一化部分,将所有数据转换为比例:
# 总人数取第一天的总和(假设无死亡,总人数全程不变) total_pop = s[0] + i[0] + r[0] s_normalized = [num / total_pop for num in s] i_normalized = [num / total_pop for num in i] r_normalized = [num / total_pop for num in r] # 绘图时替换为归一化后的I/R ax.plot(days, s_normalized, label='易感者(S)') ax.plot(days, i_normalized, label='感染者(I)') ax.plot(days, r_normalized, label='康复者(R)')
内容的提问来源于stack exchange,提问作者Hebe
相关产品推荐
相关产品推荐

