基于Python实现的分组检测

基于Python实现的分组检测

引言

分组检测是当今医学中经常出现的一种对疾病检测的有效方法。对于收集咽拭子样本并进行检测这个操作是需要一定成本的,尤其是疫情突然爆发,在短时间内,我们需要在当地众多居民中检测出携带病毒的个体,在新冠患病率不太高的地区,如果我们对众多个体进行逐个检测,可定会造成很大的浪费,因为其中大部分人是不需要检测的。对于这个问题,分组检测可以有效解决。运用python编程技术和概率论相关知识可以轻松验证数学期望的合理性

1.问题提出

在一个人数很多的团体中检测新型冠状病毒的携带者,有N个人进行测试,该集体中患病率为p,每个样本是否患病是相互独立的,现有两种检测方法:(1)逐个检测(2)按x个人一组进行分组,把x个人的咽拭子样本混合在一起,如果混合样本呈现阳性,就说明在这x个人中有人患病,然后把这x个人的样本再检测一次。如果x个人中没有人患病,则该组只需检测1次,若有人患病,则需检测x+1次。
(1)验证化验次数的数学期望函数的合理性
(2)分组人数取何值(在某有效范围内)时,节省的工作效率最高
(3)当患病率控制在什么范围内,分组检测的方法有效

2.验证化验次数数学期望函数的合理性

2.1样本来源:
2020年10月11日,青岛市发现3例新冠肺炎无症状感染者,随后组织开展大规模流调排查和分类检测。截至2020年11月16日18时,共收集样本10899145份。
假设这108万样本分5轮进行检测,有10个检测点,每次检测21800份,青岛地区患病率为0.01。
2.2方法简述
本次取证通过对比两条曲线(x为分组人数,y为检测次数)作比较得出结论。曲线一:以2-100的连续整数作为x,通过期望计算公式计算y。曲线二:以2-100之间的连续整数作为x,并根据x进行分组:如果21800%x=0,则共有21800/x组。如果21800%x!=0,则共有21800/x+1组,最后一组的人数为21800%x。利用random包生成与权重有关的随机样本(在样本中,测试结果为阳性的是1,结果为阴性的是1)。如果在一组中包含1,则该组的检测次数为x+1,反之,检测次数为1。每组检测次数相加即为x对应的y.
2.3代码展示


```python
def count_exception(sumSamples,mobidity,x):         #计算期望的函数
    f=(sumSamples//x)*(1*(1-mobidity)**x+(x+1)*(1-(1-mobidity)**x))
    return f
'''青岛核酸检测'''
import random
import matplotlib.pyplot as plt
import numpy as np
sumSamples=21800
mobidity=0.01
def weighted_random(weights):                 #权重随机数
    number=random.random()*sum(weights.values())
    for x,p in weights.items():
        if number<p:
            break
    return x
def creat_samples(num,weights):             #根据权重产生样本
    samples=[]
    for i in range(num):
        samples.append(weighted_random(weights))
    return samples
weights={1:mobidity,0:1-mobidity}
samples=creat_samples(sumSamples, weights)
#print(samples)
#ro_visualization
'''
factors=[factor for factor in range(2,100) if not sumSamples%factor]
x=np.array(factors)
f=count_exception(sumSamples, mobidity, x)
print(x)
print(f)
print(type(x),type(f))
plt.plot(x, f,'ro')
'''

#产生分组人数为range(2,100)区间的公式化期望函数
factors1=[factor for factor in range(2,100)]
x=np.array(factors1)
f1=count_exception(sumSamples, mobidity, x)
plt.plot(f1, 'b')

#产生分组人数为range(2,100)区间的随机产生样本曲线
samples=creat_samples(sumSamples, weights)
#print(len(samples))
#print(samples)
#numGroup=sumSamples//factors1 if not sumSamples%factors1 else 'error'
def sum_test(samples,fi):         #fi为factors中的一个元素numEachGroup
    numGroup=sumSamples//fi   
    sumTest=0
    minTest=1
    maxTest=fi+1
    #print(numGroup)
    for group in range(numGroup):
        startPos=group*fi
        endPos=startPos+fi
        eachGroupSample=samples[startPos:endPos]
        #print('开始位置与结束位置:',startPos,endPos)
        #print("每组中的元素值:",eachGroupSample)
        if 1 in eachGroupSample:
            sumTest+=maxTest
        else:
            sumTest+=minTest
    if sumSamples%fi:
        m=sumSamples%fi
        eachGroupSample=samples[len(samples)-m:len(samples)]
        if 1 in eachGroupSample:
            sumTest+=sumSamples%fi+1
        else:
            sumTest+=minTest            
    return sumTest
sumTest=[] 
factors=[factor for factor in range(2,100)]
for i in factors1:
    sumTest.append(sum_test(samples, i))
#print(sumTest)
plt.plot(factors1, sumTest,'r')
plt.show()

2.4结果及分析
在这里插入图片描述

蓝色曲线为根据分组检测数学期望函数计算所得的分组人数与检测次数之间的关系;
红色权限为根据分组人数产生随机样本并计算检测次数得到的曲线关系
由图像可得:两条曲线非常相近,检验次数数学期望计算公式与现实规律基本相符,具有合理性。

3.探究分组人数上限及最优分组人数

3.1方法简介
已知样本总量,患病率、期望最大工作量(%)。分组人数为2-100之间的连续整数,利用期望公式计算检测次数的期望。期望与样本总数做比值即为实际工作量,如果该实际工作量大于期望最大工作量则返回最大分组人数。
3.2代码展示

def count_exception(sumSamples,mobidity,x):
    f=(sumSamples//x)*(1*(1-mobidity)**x+(x+1)*(1-(1-mobidity)**x))
    return f
#分组上限函数(max_factors) 注:rate参数
def max_numGroup(sumSamples,mobidity,rate):   
    factors=[factor for factor in range(2,100)]   #在一组连续的数中
    max_numEachGroup=0
    for i in factors:
        test_rate=count_exception(sumSamples, mobidity, i)//sumSamples
        #print(test_rate)
        if test_rate>rate:
            max_numEachGroup=i
            break
        else:
            max_numEachGroup=i
    return max_numEachGroup
print(max_numGroup(21800,0.1,0.5))
mobidity=0.1
sumSamples=21800
import numpy as np
import matplotlib.pyplot as plt
factors=[factor for factor in range(2,max_numGroup(sumSamples, mobidity, 0.5)) if not sumSamples%factor]
x=np.array(factors)
f=count_exception(sumSamples, mobidity, x)
print(x)
print(f)
print(type(x),type(f))
plt.plot(x, f,'ro')

3.3结果及分析
在这里插入图片描述

当样本总人数为21800,患病率为0.1,期望最大工作量为0.5,得到分组人数上限为34.
分组人数为2-34之间且能被总样本人数整除的整数,分组人数的列表为[ 2 4 5 8 10 20 25 40 50],分组人数与检测次数之间的散点图。
当分组人数为4时,检测次数最少。

4.患病率控制在什么范围内,分组检测的方法有效

4.1方法简介
以患病率作为变量,分组人数为2-100之间的整数,运用检测次数数学期望函数计算检测次数。形成患病率为x变量,人均检测次数为y变量的曲线进行比较。人均检测次数为总检测次数与样本总量的比值(当人均检测次数大于1时,分组检测方法无效;当人均检测次数小于1时,分组检测次数有效)
4.2代码展示

import random
def count_exception(sumSamples,mobidity,x):
    f=(sumSamples//x)*(1*(1-mobidity)**x+(x+1)*(1-(1-mobidity)**x))
    return f
def weighted_random(weights):
    number=random.random()*sum(weights.values())
    for x,p in weights.items():
        if number<p:
            break
    return x
def creat_samples(num,weights):
    samples=[]
    for i in range(num):
        samples.append(weighted_random(weights))
    return samples
def max_numGroup(sumSamples,mobidity,rate):   
    factors=[factor for factor in range(2,100)]   #在一组连续的数中
    max_numEachGroup=0
    for i in factors:
        test_rate=count_exception(sumSamples, mobidity, i)//sumSamples
        #print(test_rate)
        if test_rate>rate:
            max_numEachGroup=i
            break
        else:
            max_numEachGroup=i
    return max_numEachGroup

import matplotlib.pyplot as plt
mobidity_list=[0.05,0.2,0.35,0.5,0.65,0.8,0.95]
sumSamples=10000
rate=0.7
def sum_test(samples,fi):         #fi为factors中的一个元素numEachGroup
    numGroup=sumSamples//fi   
    sumTest=0
    minTest=1
    maxTest=fi+1
    #print(numGroup)
    for group in range(numGroup):
        startPos=group*fi
        endPos=startPos+fi
        eachGroupSample=samples[startPos:endPos]
        #print('开始位置与结束位置:',startPos,endPos)
        #print("每组中的元素值:",eachGroupSample)
        if 1 in eachGroupSample:
            sumTest+=maxTest
        else:
            sumTest+=minTest
    if sumSamples%fi:
        m=sumSamples%fi
        eachGroupSample=samples[len(samples)-m:len(samples)]
        if 1 in eachGroupSample:
            sumTest+=sumSamples%fi+1
        else:
            sumTest+=minTest            
    return sumTest
sumTest=[] 
factors1=[factor for factor in range(2,100) if not sumSamples%factor]
for i in factors1:
    sumTest.append(sum_test(sumSamples, i))
#print(sumTest)
plt.plot(factors1, sumTest,'r')
plt.show()
for mobidity in mobidity_list:
    saveRate_list=[]
    save_rate=0
    weights={1:mobidity,0:1-mobidity}
    samples=creat_samples(sumSamples, weights)
    factors=[i for i in range(2,max_numGroup(sumSamples, mobidity, rate)) if not sumSamples%i]
    print(factors)
    for fi in factors:        
        sumTest=sum_test(samples,fi)
        save_rate=sumTest/sumSamples
        saveRate_list.append(sumTest)
    print(saveRate_list)
    plt.plot(factors,saveRate_list)

4.3结果及分析
在这里插入图片描述

样本总量为10000,分组人数为2-100之间的整数
蓝橙绿红蓝曲线分别为患病率(x变量)为0.05、0.2、0.35、0.5、0.65时的曲线。
由图可知:当患病率小于0.35时,分组检测的方法更有效。患病率大于0.35,分组检测的方法基本不能减少工作量

  • 9
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
核酸检测预登记系统是一种用于管理和记录核酸检测信息的系统。在疫情期间,核酸检测成为了防控疫情的重要手段之一,因此需要一个高效、精准、可靠的管理系统来支持日常工作。本文将介绍一种基于TP6框架开发的核酸检测预登记系统。 系统架构 系统采用了MVC(Model-View-Controller)架构,前端采用Bootstrap框架,后端采用TP6框架,数据库采用MySQL数据库。系统主要分为前台页面和后台管理页面两部分。 系统功能 1. 用户注册、登录、退出功能。用户可以通过注册账号登录系统,进行后续操作。 2. 核酸检测预登记功能。用户可以预先填写核酸检测相关信息,包括姓名、联系方式、身份证号、检测时间等信息。 3. 核酸检测结果上传功能。用户可以将核酸检测结果上传到系统中,包括检测报告、身份证照片等信息。 4. 核酸检测结果查询功能。用户可以在系统中查询自己的核酸检测结果,包括检测时间、检测结果等信息。 5. 后台管理功能。管理员可以管理用户信息、核酸检测信息、检测结果信息等。 系统优势 1. 系统具有良好的用户体验,采用了Bootstrap框架进行前端开发,界面简洁美观。 2. 系统具有灵活的功能扩展性,可以根据实际需求进行功能扩展和定制。 3. 系统具有高效的数据管理能力,采用了TP6框架和MySQL数据库,能够支持大规模数据管理和处理。 总结 本文介绍了一种基于TP6框架开发的核酸检测预登记系统,该系统具有良好的用户体验、灵活的功能扩展性和高效的数据管理能力,能够满足日常核酸检测管理的需求。同时,该系统还有待进一步完善和优化,以适应不同场景下的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值