今年(2020年)是注定要铭记史册的一年,从年初开始新冠疫情,席卷了全球,中国人民众志成城,为战胜疫情做出了巨大牺牲。最近北京疫情形式又变得严峻,面对疫情我们不能掉以轻心。今天我们模拟一下病毒的扩散过程,增强对疫情的认识之外,还可以了解下 Python 模拟技术,开干

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:1097524789

解决思路

我们将模拟过程分为 数据模型 和 展示 两部分 首先设置正态分布的人群,然后在其中随机设置携带者,在设置传染条件,和潜伏期时间,最后,用迭代模拟时间,观察病毒的传播过程,先看下效果:

数据模型

模拟人群

假设城市环境,人群集中度呈正态分布,即中心地带集中度高,边缘地带集中度低,每个人都是一个平面坐标位置,随机产生在平面中心位置的一组坐标点来代表一个人

我们用 numpy 的随机机制产生模拟数据:

numpy 安装: pip install numpy

import numpy as npcount = 100
people = np.random.normal(250, 100, (count, 2))
numpy.random.normal
loc
scale
size

人的属性除了位置,还需要有状态,我们用(0,1,2)来表示 健康、携带 和 确诊

由于 numpy 产生的事数据集合,所以状态数据用单独的数组表示,数组长度与人的数量相等:

import numpy as npcount = 100
status = np.array([0] * count)
  • array 方法可以产生一个数组,[0] 表示初始化数组,元素值为 0,即健康,然后乘以元素数量就可以得到初始化为 0 的数组。

有了人群的初始状态,可以为随机设置一些病毒携带者,通过一个随机过程来设置:

import numpy as npcount = 100
index = np.random.randint(0, count)
status[index] = 1
  • randint 可以在给定参数之间随机产生一个整数,我们在 0 和 人数的范围内得到一个随机数,作为携带者的下标
  • 如果需要设置多个携带者,可以循环此过程,但需要排除掉状态已经是携带者的情况

另外由于病毒有潜伏期,所以需要记录感染的时间,以便在达到潜伏条件后变为确诊:

import numpy as npcount = 100
timer = np.array([0] * count)
  • 感染时间和状态类似,是一个数量为人数的数组

最后,一个人有三个属性:位置、状态和感染时间,在模拟过程中,会不断调整这些属性

模拟移动

人群是运动的,需要设置一个随机运动的机制,这里采用随机小幅度移动来模拟人群移动,从而产生:

count = 100
movement = np.random.normal(0, 1, (count, 2))normal = np.random.normal(0, 1, count)
switch = np.where(normal < x, 1, 0)
movement[switch == 0] = 0people = people + movement
  • 产生一个中心点为 0,幅度为 1 的与人数相对的微小移动坐标数组 movement
  • 为了一定比例不移动的情况,在得到一个正态一维数组,
  • 并对数值进行筛选和归一,小于 0 的设置为 1,其他的设置为 0,做成一个动态开关
  • 对移动数据中,对应开关为 0 的位置设置移动为 0,即不移动,从而随意模拟一下不移动的情况

模拟传播

新冠病毒会在人与人之间传播,主要取决于接触程度,现实中接触过程很复杂,这里我们用人与人之间的距离作为传播依据,设置一个传播临界距离,健康者与携带者或者确诊者距离小于这个临界值,就会被传染

距离怎么计算呢,我们采用欧拉距离公式来计算,我们模拟的是平面位置,所以采用二维欧拉距离公式,假设平面中有两个坐标点 ($x_1$, $y_1$) 和 ($x_2$, $y_2$),那么他们之间的距离公式为:

$\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2}$

如何引用这个公式呢?最容易想到的是用循环将传播源(携带者和确诊者)与每一个健康者之间的距离都算出来,将距离小于临界值的健康者标记为携带 不过 numpy 为我们提供了强大的集合运算能力,像写公式一样完成运算,而无需关注程序细节,先看代码:

import numpy as npsafe_distance = 5
for inf in people[(status == 1) | (status == 2)]:dm = (people - inf) ** 2  # (x2-x1)^2 , (y2-y1)^2d = dm.sum(axis=1) ** 0.5sorted_index = d.argsort()for i in sorted_index:if d[i] >= safe_distance:break  # 超出范围,不用管了if status[i] > 0: # 已经感染的排除掉continuestatus[i] = 1 # 标记为感染
  • 设置临界距离为 5
  • 从人中选出已经携带和确诊者的位置坐标
    status == 1
    
  • 遍历传播源的位置,并计算与每个人的距离,采用的是欧拉距离公式
    people - inf
    
  • 对距离进行排序,并且获得距离集合的索引集合 sorted_index,这个很有用
  • 遍历索引集合,一旦发现大于等于安全距离的情况,就退出遍历,否则标记为感染

如果更实际一些,可以加入感染概率的考量,即并非每个在临界距离内的健康者都会感染

模拟潜伏期

携带者需要经过一段时间的潜伏期,才会成为确诊者,例如潜伏期一般 3 到 7 天,14 天一定会成为确诊者:

days = 10 # 时间线 表示从模拟开始到现在的天数
dt = days - timer
d = np.random.randint(3, 7)
timer[(status == 1) & ((dt == d) | (dt > 14))] = days
status[(status == 1) & ((dt == d) | (dt > 14))] += 1
  • days 表示模拟的天数,例如现在模拟到到 10 天
  • dt 是计算一个 timer 数组与天数的差值的数组
  • 然后随机一个 3 到 7 之间的数,表示当时的确诊天数
  • 选择状态为携带的 timer,并且时间间隔等于本次确诊天数或者时间间隔大于14天,如果符合条件标记确证时间,即哪一天确诊的
  • 用同样的条件将状态为携带的标记为确证

图形化

有了数据模型,下一步是将数据展示出来,可选择的方式很多,这里我们选择 pygame 库,作为展示方式

pygame 是一个 2D 游戏工具,简单易用,通过 pip install pygame 安装

初始化

初始化 pygame :

import pygame, sys
from pygame.locals import *# 初始化pygame
pygame.init()# 设置窗口与窗口标题
windowSurface = pygame.display.set_mode((WIDTH,HEIGHT),0,8)
pygame.display.set_caption('疫情模拟')# 填充背景色
WHITE = (255,255,255)
windowSurface.fill(WHITE)

绘制模拟点

将人模拟成屏幕上的小圆点,根据不同状态设置不同颜色,例如正常为黑色,携带为粉色,确诊为红色:

POINT_RADIUS = 5
COLORS = [(0,0,0), (255,192,203),(255,0,0)]for i in range(len(status)):  # 健康x_point = people[i][0]y_point = people[i][1]pygame.draw.circle(windowSurface,COLORS[status[i]],(int(x_point), int(y_point)), POINT_RADIUS)
  • 循环人的状态,得到状态索引
  • 用索引定位到人,得到人的坐标
  • 通过 pygame.draw.circle 绘制到 windowSurface 上,其中填充颜色通过状态值作为索引获取

事件循环

动态效果的实质时不断的刷新绘图,需要有个循环直接,动态更新:

while True:windowSurface.fill(WHITE)  # 设置画布背景 起到擦除的作用for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()# 绘制模拟点<省略代码># 更新到窗口中pygame.display.update()time.sleep(0.1)
  • pygame.event.get 可以获取到收的意外事件,这里的逻辑时,如果收到退出事件,则退出程序
  • pygame.display.update() 用于将绘制更新到屏幕上
  • 每次绘制完成等等 0.2 秒,以便观察结果

将上面部分组合起来,运行就可以看到模拟效果了

总结

今天的模拟实验,主要依赖于 numpy 的随机机制,通过练习可以看到 numpy 处理在数据处理方面的强大功能。另外简单接触了 pygame,可以更高效的绘制动画效果,应为 pygame 就是为制作简单游戏而生的。 最后文章中主要以设计思路为主描述模拟程序的构成和原理,代码示例中有完整的可运行代码,欢迎把玩交流。

Python 告诉你疫情扩散有多可怕相关推荐

  1. python最难的地方_全国 41611 个景点,程序员用 Python 告诉你哪些地方最值得一游!...

    原标题:全国 41611 个景点,程序员用 Python 告诉你哪些地方最值得一游! 经常听到别人说"世界那么大,我想去看看".在有机会走出国门之前,还是先把祖国走一圈吧.都知道中 ...

  2. 基于Python的一个疫情传播可视化模拟实验

    大家好! 新冠疫情已经持续有快两年了,给大家的工作和生活都带了极大的影响.在疫情之初,我曾经看到过一个对疫情传播发展的可视化模拟.现在回头看,确实如模拟中所示,只要疫情没完全消除,都存在再度传播的风险 ...

  3. Python告诉你:为何年终奖多发一元,到手却少两千多?

    作者 | shenzhongqiang 来源 | Python数据与分析(ID:ML_Python) 年终奖多发一元,到手却要少两千多,甚至更多.听到这个消息的时候,大家是不是觉得有点意外,意外之余还 ...

  4. 啥是佩奇?Python告诉你

    作者 | 丁彦君 来源 | 恋习Python 昨天, 被<啥是佩奇>这支广告片刷屏了. 佩奇明明是个喜剧角色, 却看哭了所有人. ▼ <啥是佩奇>??? 快过年了 在农村爷爷给 ...

  5. 11月30日云栖精选夜读 | 用Python告诉你,现在的房租有多高?

    杭州房租:钱塘两岸最高,奥体单间达4830元/月.不少人感叹:躲过了高房价,躲不过高房租,面对房租上涨,感觉身体被掏空.2018年的这个夏天,房租正在成为摧垮年轻人的"第一根稻草" ...

  6. python哪本好-在众多小说中,Python告诉你哪本小说好看

    Python Python开发 Python语言 在众多小说中,Python告诉你哪本小说好看 前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及 ...

  7. python125免费教程,125 个视频成就千万级网红,Python 告诉你李子柒都在拍些什么?...

    原标题:125 个视频成就千万级网红,Python 告诉你李子柒都在拍些什么? 作者 |Mika,数据 |真达 后期 |Mika.泽龙 责编 | 郭芮 来源 | CDA数据分析师 今天我们来聊聊把生活 ...

  8. 抖音很火的存钱计划,让python告诉你总共可以存到多少钱!

    抖音上有个很火的存钱计划,说是第一天存1块钱,第二天存2块钱,第三天存3块钱.....依此类推存365天,总共可以存到多少钱,我们现在用python告诉你怎么做: #定个初始存入金额 money = ...

  9. 服务器可视化_疫情来袭,30分钟学会用python开发部署疫情可视化网站

    2019-nCov疫情实时数据可视化--30分钟python快速版 疫情来袭,宅在家不如学习用python如何开发并部署一个疫情实时追踪可视化页面.页面预览 本文将介绍如何使用python开发网站,「 ...

最新文章

  1. IOS笔记 #pragma mark的用法
  2. gulp-sass_如果您是初学者,如何使用命令行设置Gulp-sass
  3. os.path.dirname(path) 返回文件的绝对路径
  4. pythonexe32位-如何使用pyinstaller打包32位的exe
  5. 读入两个字符串java_编写一个Java应用程序,从键盘读取用户输入两个字符串,并重载3个strAdd函数...
  6. linux删除物理卷命令,如何安全的删除Linux LVM中的PV物理卷(硬盘或分区
  7. C#的变迁史02 - C# 2.0篇
  8. 华为双系统手机可以刷成单系统_「冯站长之家」今日聚焦:重大突破!华为手机鸿蒙系统2.0,正式面世!骂华为的“喷子”,可以休矣!...
  9. android 时间戳 转日期格式,在Android中转换为简单日期格式或Unix时间戳日期?
  10. 高逼格又实用的Linux命令:持续更新中
  11. jquery新版本旧版本之间的坑
  12. GFP_KERNEL的作用
  13. mysql 或hive left join不加关联条件
  14. SQL Server海量数据查询代码优化建议
  15. 动态域名内网穿透(永久免费)
  16. 计算机里的声卡的主要作用,声卡是什么?他的主要作用有哪些?
  17. 北森{“message“:“un-authorized“}
  18. 网络(十三)之ACL的高级应用
  19. 手机app抓包,无视SSLPinning
  20. 小米生活早报早间新闻入口/凤凰FM头条速递入口

热门文章

  1. mysql-查询例题大全
  2. Linux中的文件被异常删除的排查思路
  3. springboot(四)——@EnableConfigurationProperties是如何起作用的你知道吗
  4. Android进阶:自定义视频播放器开发(下)
  5. 如何解决安卓项目在Android Studio无法打开
  6. win10配置gcc编译环境
  7. 【博客话题】爱上Linux的N+1个理由
  8. IT人母亲的美国之行(4)
  9. 文档转换乱码异常解决:unoconv openoffice libreoffice
  10. Dubbo面试 - dubbo的工作原理